Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:07

0001 /**
0002   ******************************************************************************
0003   * @file    stm32h7xx_hal_hash.c
0004   * @author  MCD Application Team
0005   * @brief   HASH HAL module driver.
0006   *          This file provides firmware functions to manage the following
0007   *          functionalities of the HASH peripheral:
0008   *           + Initialization and de-initialization methods
0009   *           + HASH or HMAC processing in polling mode
0010   *           + HASH or HMAC processing in interrupt mode
0011   *           + HASH or HMAC processing in DMA mode
0012   *           + Peripheral State methods
0013   *           + HASH or HMAC processing suspension/resumption
0014   *
0015   ******************************************************************************
0016   * @attention
0017   *
0018   * Copyright (c) 2017 STMicroelectronics.
0019   * All rights reserved.
0020   *
0021   * This software is licensed under terms that can be found in the LICENSE file
0022   * in the root directory of this software component.
0023   * If no LICENSE file comes with this software, it is provided AS-IS.
0024   *
0025   ******************************************************************************
0026   @verbatim
0027  ===============================================================================
0028                      ##### How to use this driver #####
0029  ===============================================================================
0030     [..]
0031     The HASH HAL driver can be used as follows:
0032 
0033     (#)Initialize the HASH low level resources by implementing the HAL_HASH_MspInit():
0034         (##) Enable the HASH interface clock using __HASH_CLK_ENABLE()
0035         (##) When resorting to interrupt-based APIs (e.g. HAL_HASH_xxx_Start_IT())
0036             (+++) Configure the HASH interrupt priority using HAL_NVIC_SetPriority()
0037             (+++) Enable the HASH IRQ handler using HAL_NVIC_EnableIRQ()
0038             (+++) In HASH IRQ handler, call HAL_HASH_IRQHandler() API
0039         (##) When resorting to DMA-based APIs  (e.g. HAL_HASH_xxx_Start_DMA())
0040             (+++) Enable the DMAx interface clock using
0041                    __DMAx_CLK_ENABLE()
0042             (+++) Configure and enable one DMA stream to manage data transfer from
0043                 memory to peripheral (input stream). Managing data transfer from
0044                 peripheral to memory can be performed only using CPU.
0045             (+++) Associate the initialized DMA handle to the HASH DMA handle
0046                 using  __HAL_LINKDMA()
0047             (+++) Configure the priority and enable the NVIC for the transfer complete
0048                 interrupt on the DMA stream: use
0049                  HAL_NVIC_SetPriority() and
0050                  HAL_NVIC_EnableIRQ()
0051 
0052     (#)Initialize the HASH HAL using HAL_HASH_Init(). This function:
0053         (##) resorts to HAL_HASH_MspInit() for low-level initialization,
0054         (##) configures the data type: 1-bit, 8-bit, 16-bit or 32-bit.
0055 
0056     (#)Three processing schemes are available:
0057         (##) Polling mode: processing APIs are blocking functions
0058              i.e. they process the data and wait till the digest computation is finished,
0059              e.g. HAL_HASH_xxx_Start() for HASH or HAL_HMAC_xxx_Start() for HMAC
0060         (##) Interrupt mode: processing APIs are not blocking functions
0061                 i.e. they process the data under interrupt,
0062                 e.g. HAL_HASH_xxx_Start_IT() for HASH or HAL_HMAC_xxx_Start_IT() for HMAC
0063         (##) DMA mode: processing APIs are not blocking functions and the CPU is
0064              not used for data transfer i.e. the data transfer is ensured by DMA,
0065                 e.g. HAL_HASH_xxx_Start_DMA() for HASH or HAL_HMAC_xxx_Start_DMA()
0066                 for HMAC. Note that in DMA mode, a call to HAL_HASH_xxx_Finish()
0067                 is then required to retrieve the digest.
0068 
0069     (#)When the processing function is called after HAL_HASH_Init(), the HASH peripheral is
0070        initialized and processes the buffer fed in input. When the input data have all been
0071        fed to the Peripheral, the digest computation can start.
0072 
0073     (#)Multi-buffer processing is possible in polling, interrupt and DMA modes.
0074         (##) In polling mode, only multi-buffer HASH processing is possible.
0075              API HAL_HASH_xxx_Accumulate() must be called for each input buffer, except for the last one.
0076              User must resort to HAL_HASH_xxx_Accumulate_End() to enter the last one and retrieve as
0077              well the computed digest.
0078 
0079         (##) In interrupt mode, API HAL_HASH_xxx_Accumulate_IT() must be called for each input buffer,
0080              except for the last one.
0081              User must resort to HAL_HASH_xxx_Accumulate_End_IT() to enter the last one and retrieve as
0082              well the computed digest.
0083 
0084         (##) In DMA mode, multi-buffer HASH and HMAC processing are possible.
0085               (+++) HASH processing: once initialization is done, MDMAT bit must be set
0086                through __HAL_HASH_SET_MDMAT() macro.
0087              From that point, each buffer can be fed to the Peripheral through HAL_HASH_xxx_Start_DMA() API.
0088              Before entering the last buffer, reset the MDMAT bit with __HAL_HASH_RESET_MDMAT()
0089              macro then wrap-up the HASH processing in feeding the last input buffer through the
0090              same API HAL_HASH_xxx_Start_DMA(). The digest can then be retrieved with a call to
0091              API HAL_HASH_xxx_Finish().
0092              (+++) HMAC processing (requires to resort to extended functions):
0093              after initialization, the key and the first input buffer are entered
0094              in the Peripheral with the API HAL_HMACEx_xxx_Step1_2_DMA(). This carries out HMAC step 1 and
0095              starts step 2.
0096              The following buffers are next entered with the API  HAL_HMACEx_xxx_Step2_DMA(). At this
0097              point, the HMAC processing is still carrying out step 2.
0098              Then, step 2 for the last input buffer and step 3 are carried out by a single call
0099              to HAL_HMACEx_xxx_Step2_3_DMA().
0100 
0101              The digest can finally be retrieved with a call to API HAL_HASH_xxx_Finish().
0102 
0103 
0104     (#)Context swapping.
0105         (##) Two APIs are available to suspend HASH or HMAC processing:
0106              (+++) HAL_HASH_SwFeed_ProcessSuspend() when data are entered by software (polling or IT mode),
0107              (+++) HAL_HASH_DMAFeed_ProcessSuspend() when data are entered by DMA.
0108 
0109         (##) When HASH or HMAC processing is suspended, HAL_HASH_ContextSaving() allows
0110             to save in memory the Peripheral context. This context can be restored afterwards
0111             to resume the HASH processing thanks to HAL_HASH_ContextRestoring().
0112 
0113         (##) Once the HASH Peripheral has been restored to the same configuration as that at suspension
0114              time, processing can be restarted with the same API call (same API, same handle,
0115              same parameters) as done before the suspension. Relevant parameters to restart at
0116              the proper location are internally saved in the HASH handle.
0117 
0118     (#)Call HAL_HASH_DeInit() to deinitialize the HASH peripheral.
0119 
0120      *** Remarks on message length ***
0121      ===================================
0122      [..]
0123       (#) HAL in interruption mode (interruptions driven)
0124 
0125         (##)Due to HASH peripheral hardware design, the peripheral interruption is triggered every 64 bytes.
0126         This is why, for driver implementation simplicity s sake, user is requested to enter a message the
0127         length of which is a multiple of 4 bytes.
0128 
0129         (##) When the message length (in bytes) is not a multiple of words, a specific field exists in HASH_STR
0130         to specify which bits to discard at the end of the complete message to process only the message bits
0131         and not extra bits.
0132 
0133         (##) If user needs to perform a hash computation of a large input buffer that is spread around various places
0134         in memory and where each piece of this input buffer is not necessarily a multiple of 4 bytes in size, it becomes
0135         necessary to use a temporary buffer to format the data accordingly before feeding them to the Peripheral.
0136         It is advised to the user to
0137        (+++) achieve the first formatting operation by software then enter the data
0138        (+++) while the Peripheral is processing the first input set, carry out the second formatting
0139         operation by software, to be ready when DINIS occurs.
0140        (+++) repeat step 2 until the whole message is processed.
0141 
0142      [..]
0143       (#) HAL in DMA mode
0144 
0145         (##) Again, due to hardware design, the DMA transfer to feed the data can only be done on a word-basis.
0146         The same field described above in HASH_STR is used to specify which bits to discard at the end of the
0147         DMA transfer to process only the message bits and not extra bits. Due to hardware implementation,
0148         this is possible only at the end of the complete message. When several DMA transfers are needed to
0149         enter the message, this is not applicable at the end of the intermediary transfers.
0150 
0151         (##) Similarly to the interruption-driven mode, it is suggested to the user to format the consecutive
0152         chunks of data by software while the DMA transfer and processing is on-going for the first parts of
0153         the message. Due to the 32-bit alignment required for the DMA transfer, it is underlined that the
0154         software formatting operation is more complex than in the IT mode.
0155 
0156      *** Callback registration ***
0157      ===================================
0158      [..]
0159       (#) The compilation define  USE_HAL_HASH_REGISTER_CALLBACKS when set to 1
0160           allows the user to configure dynamically the driver callbacks.
0161           Use function HAL_HASH_RegisterCallback() to register a user callback.
0162 
0163       (#) Function HAL_HASH_RegisterCallback() allows to register following callbacks:
0164             (+) InCpltCallback    : callback for input completion.
0165             (+) DgstCpltCallback  : callback for digest computation completion.
0166             (+) ErrorCallback     : callback for error.
0167             (+) MspInitCallback   : HASH MspInit.
0168             (+) MspDeInitCallback : HASH MspDeInit.
0169           This function takes as parameters the HAL peripheral handle, the Callback ID
0170           and a pointer to the user callback function.
0171 
0172       (#) Use function HAL_HASH_UnRegisterCallback() to reset a callback to the default
0173           weak (surcharged) function.
0174           HAL_HASH_UnRegisterCallback() takes as parameters the HAL peripheral handle,
0175           and the Callback ID.
0176           This function allows to reset following callbacks:
0177             (+) InCpltCallback    : callback for input completion.
0178             (+) DgstCpltCallback  : callback for digest computation completion.
0179             (+) ErrorCallback     : callback for error.
0180             (+) MspInitCallback   : HASH MspInit.
0181             (+) MspDeInitCallback : HASH MspDeInit.
0182 
0183       (#) By default, after the HAL_HASH_Init and if the state is HAL_HASH_STATE_RESET
0184           all callbacks are reset to the corresponding legacy weak (surcharged) functions:
0185           examples HAL_HASH_InCpltCallback(), HAL_HASH_DgstCpltCallback()
0186           Exception done for MspInit and MspDeInit callbacks that are respectively
0187           reset to the legacy weak (surcharged) functions in the HAL_HASH_Init
0188           and HAL_HASH_DeInit only when these callbacks are null (not registered beforehand)
0189           If not, MspInit or MspDeInit are not null, the HAL_HASH_Init and HAL_HASH_DeInit
0190           keep and use the user MspInit/MspDeInit callbacks (registered beforehand).
0191 
0192           Callbacks can be registered/unregistered in READY state only.
0193           Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
0194           in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used
0195           during the Init/DeInit.
0196           In that case first register the MspInit/MspDeInit user callbacks
0197           using HAL_HASH_RegisterCallback before calling HAL_HASH_DeInit
0198           or HAL_HASH_Init function.
0199 
0200           When The compilation define USE_HAL_HASH_REGISTER_CALLBACKS is set to 0 or
0201           not defined, the callback registering feature is not available
0202           and weak (surcharged) callbacks are used.
0203 
0204   @endverbatim
0205   ******************************************************************************
0206   */
0207 
0208 /* Includes ------------------------------------------------------------------*/
0209 #include "stm32h7xx_hal.h"
0210 
0211 
0212 /** @addtogroup STM32H7xx_HAL_Driver
0213   * @{
0214   */
0215 #if defined (HASH)
0216 
0217 /** @defgroup HASH  HASH
0218   * @ingroup RTEMSBSPsARMSTM32H7
0219   * @brief HASH HAL module driver.
0220   * @{
0221   */
0222 
0223 #ifdef HAL_HASH_MODULE_ENABLED
0224 
0225 /* Private typedef -----------------------------------------------------------*/
0226 /* Private define ------------------------------------------------------------*/
0227 /** @defgroup HASH_Private_Constants HASH Private Constants
0228   * @ingroup RTEMSBSPsARMSTM32H7
0229   * @{
0230   */
0231 
0232 /** @defgroup HASH_Digest_Calculation_Status HASH Digest Calculation Status
0233   * @ingroup RTEMSBSPsARMSTM32H7
0234   * @{
0235   */
0236 #define HASH_DIGEST_CALCULATION_NOT_STARTED       ((uint32_t)0x00000000U) /*!< DCAL not set after input data written in DIN register */
0237 #define HASH_DIGEST_CALCULATION_STARTED           ((uint32_t)0x00000001U) /*!< DCAL set after input data written in DIN register     */
0238 /**
0239   * @}
0240   */
0241 
0242 /** @defgroup HASH_Number_Of_CSR_Registers HASH Number of Context Swap Registers
0243   * @ingroup RTEMSBSPsARMSTM32H7
0244   * @{
0245   */
0246 #define HASH_NUMBER_OF_CSR_REGISTERS              54U     /*!< Number of Context Swap Registers */
0247 /**
0248   * @}
0249   */
0250 
0251 /** @defgroup HASH_TimeOut_Value HASH TimeOut Value
0252   * @ingroup RTEMSBSPsARMSTM32H7
0253   * @{
0254   */
0255 #define HASH_TIMEOUTVALUE                         1000U   /*!< Time-out value  */
0256 /**
0257   * @}
0258   */
0259 
0260 /** @defgroup HASH_DMA_Suspension_Words_Limit HASH DMA suspension words limit
0261   * @ingroup RTEMSBSPsARMSTM32H7
0262   * @{
0263   */
0264 #define HASH_DMA_SUSPENSION_WORDS_LIMIT             20U   /*!< Number of words below which DMA suspension is aborted */
0265 /**
0266   * @}
0267   */
0268 
0269 /**
0270   * @}
0271   */
0272 
0273 /* Private macro -------------------------------------------------------------*/
0274 /* Private variables ---------------------------------------------------------*/
0275 /* Private function prototypes -----------------------------------------------*/
0276 /** @defgroup HASH_Private_Functions HASH Private Functions
0277   * @ingroup RTEMSBSPsARMSTM32H7
0278   * @{
0279   */
0280 static void HASH_DMAXferCplt(DMA_HandleTypeDef *hdma);
0281 static void HASH_DMAError(DMA_HandleTypeDef *hdma);
0282 static void HASH_GetDigest(uint8_t *pMsgDigest, uint8_t Size);
0283 static HAL_StatusTypeDef HASH_WaitOnFlagUntilTimeout(HASH_HandleTypeDef *hhash, uint32_t Flag, FlagStatus Status,
0284                                                      uint32_t Timeout);
0285 static HAL_StatusTypeDef HASH_WriteData(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size);
0286 static HAL_StatusTypeDef HASH_IT(HASH_HandleTypeDef *hhash);
0287 static uint32_t HASH_Write_Block_Data(HASH_HandleTypeDef *hhash);
0288 static HAL_StatusTypeDef HMAC_Processing(HASH_HandleTypeDef *hhash, uint32_t Timeout);
0289 /**
0290   * @}
0291   */
0292 
0293 /** @defgroup HASH_Exported_Functions HASH Exported Functions
0294   * @ingroup RTEMSBSPsARMSTM32H7
0295   * @{
0296   */
0297 
0298 /** @defgroup HASH_Exported_Functions_Group1 Initialization and de-initialization functions
0299   * @ingroup RTEMSBSPsARMSTM32H7
0300   *  @brief    Initialization, configuration and call-back functions.
0301   *
0302 @verbatim
0303  ===============================================================================
0304               ##### Initialization and de-initialization functions #####
0305  ===============================================================================
0306     [..]  This section provides functions allowing to:
0307       (+) Initialize the HASH according to the specified parameters
0308           in the HASH_InitTypeDef and create the associated handle
0309       (+) DeInitialize the HASH peripheral
0310       (+) Initialize the HASH MCU Specific Package (MSP)
0311       (+) DeInitialize the HASH MSP
0312 
0313     [..]  This section provides as well call back functions definitions for user
0314           code to manage:
0315       (+) Input data transfer to Peripheral completion
0316       (+) Calculated digest retrieval completion
0317       (+) Error management
0318 
0319 
0320 
0321 @endverbatim
0322   * @{
0323   */
0324 
0325 /**
0326   * @brief  Initialize the HASH according to the specified parameters in the
0327             HASH_HandleTypeDef and create the associated handle.
0328   * @note   Only MDMAT and DATATYPE bits of HASH Peripheral are set by HAL_HASH_Init(),
0329   *         other configuration bits are set by HASH or HMAC processing APIs.
0330   * @note   MDMAT bit is systematically reset by HAL_HASH_Init(). To set it for
0331   *         multi-buffer HASH processing, user needs to resort to
0332   *         __HAL_HASH_SET_MDMAT() macro. For HMAC multi-buffer processing, the
0333   *         relevant APIs manage themselves the MDMAT bit.
0334   * @param  hhash HASH handle
0335   * @retval HAL status
0336   */
0337 HAL_StatusTypeDef HAL_HASH_Init(HASH_HandleTypeDef *hhash)
0338 {
0339   /* Check the hash handle allocation */
0340   if (hhash == NULL)
0341   {
0342     return HAL_ERROR;
0343   }
0344 
0345   /* Check the parameters */
0346   assert_param(IS_HASH_DATATYPE(hhash->Init.DataType));
0347 
0348 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
0349   if (hhash->State == HAL_HASH_STATE_RESET)
0350   {
0351     /* Allocate lock resource and initialize it */
0352     hhash->Lock = HAL_UNLOCKED;
0353 
0354     /* Reset Callback pointers in HAL_HASH_STATE_RESET only */
0355     hhash->InCpltCallback =  HAL_HASH_InCpltCallback;     /* Legacy weak (surcharged) input completion callback */
0356     hhash->DgstCpltCallback =  HAL_HASH_DgstCpltCallback; /* Legacy weak (surcharged) digest computation
0357                                                              completion callback */
0358     hhash->ErrorCallback =  HAL_HASH_ErrorCallback;       /* Legacy weak (surcharged) error callback */
0359     if (hhash->MspInitCallback == NULL)
0360     {
0361       hhash->MspInitCallback = HAL_HASH_MspInit;
0362     }
0363 
0364     /* Init the low level hardware */
0365     hhash->MspInitCallback(hhash);
0366   }
0367 #else
0368   if (hhash->State == HAL_HASH_STATE_RESET)
0369   {
0370     /* Allocate lock resource and initialize it */
0371     hhash->Lock = HAL_UNLOCKED;
0372 
0373     /* Init the low level hardware */
0374     HAL_HASH_MspInit(hhash);
0375   }
0376 #endif /* (USE_HAL_HASH_REGISTER_CALLBACKS) */
0377 
0378   /* Change the HASH state */
0379   hhash->State = HAL_HASH_STATE_BUSY;
0380 
0381   /* Reset HashInCount, HashITCounter, HashBuffSize and NbWordsAlreadyPushed */
0382   hhash->HashInCount = 0;
0383   hhash->HashBuffSize = 0;
0384   hhash->HashITCounter = 0;
0385   hhash->NbWordsAlreadyPushed = 0;
0386   /* Reset digest calculation bridle (MDMAT bit control) */
0387   hhash->DigestCalculationDisable = RESET;
0388   /* Set phase to READY */
0389   hhash->Phase = HAL_HASH_PHASE_READY;
0390   /* Reset suspension request flag */
0391   hhash->SuspendRequest = HAL_HASH_SUSPEND_NONE;
0392 
0393   /* Set the data type bit */
0394   MODIFY_REG(HASH->CR, HASH_CR_DATATYPE, hhash->Init.DataType);
0395   /* Reset MDMAT bit */
0396   __HAL_HASH_RESET_MDMAT();
0397   /* Reset HASH handle status */
0398   hhash->Status = HAL_OK;
0399 
0400   /* Set the HASH state to Ready */
0401   hhash->State = HAL_HASH_STATE_READY;
0402 
0403   /* Initialise the error code */
0404   hhash->ErrorCode = HAL_HASH_ERROR_NONE;
0405 
0406   /* Return function status */
0407   return HAL_OK;
0408 }
0409 
0410 /**
0411   * @brief  DeInitialize the HASH peripheral.
0412   * @param  hhash HASH handle.
0413   * @retval HAL status
0414   */
0415 HAL_StatusTypeDef HAL_HASH_DeInit(HASH_HandleTypeDef *hhash)
0416 {
0417   /* Check the HASH handle allocation */
0418   if (hhash == NULL)
0419   {
0420     return HAL_ERROR;
0421   }
0422 
0423   /* Change the HASH state */
0424   hhash->State = HAL_HASH_STATE_BUSY;
0425 
0426   /* Set the default HASH phase */
0427   hhash->Phase = HAL_HASH_PHASE_READY;
0428 
0429   /* Reset HashInCount, HashITCounter and HashBuffSize */
0430   hhash->HashInCount = 0;
0431   hhash->HashBuffSize = 0;
0432   hhash->HashITCounter = 0;
0433   /* Reset digest calculation bridle (MDMAT bit control) */
0434   hhash->DigestCalculationDisable = RESET;
0435 
0436 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
0437   if (hhash->MspDeInitCallback == NULL)
0438   {
0439     hhash->MspDeInitCallback = HAL_HASH_MspDeInit;
0440   }
0441 
0442   /* DeInit the low level hardware */
0443   hhash->MspDeInitCallback(hhash);
0444 #else
0445   /* DeInit the low level hardware: CLOCK, NVIC */
0446   HAL_HASH_MspDeInit(hhash);
0447 #endif /* (USE_HAL_HASH_REGISTER_CALLBACKS) */
0448 
0449 
0450   /* Reset HASH handle status */
0451   hhash->Status = HAL_OK;
0452 
0453   /* Set the HASH state to Ready */
0454   hhash->State = HAL_HASH_STATE_RESET;
0455 
0456   /* Initialise the error code */
0457   hhash->ErrorCode = HAL_HASH_ERROR_NONE;
0458 
0459   /* Reset multi buffers accumulation flag */
0460   hhash->Accumulation = 0U;
0461 
0462   /* Return function status */
0463   return HAL_OK;
0464 }
0465 
0466 /**
0467   * @brief  Initialize the HASH MSP.
0468   * @param  hhash HASH handle.
0469   * @retval None
0470   */
0471 __weak void HAL_HASH_MspInit(HASH_HandleTypeDef *hhash)
0472 {
0473   /* Prevent unused argument(s) compilation warning */
0474   UNUSED(hhash);
0475 
0476   /* NOTE : This function should not be modified; when the callback is needed,
0477             HAL_HASH_MspInit() can be implemented in the user file.
0478    */
0479 }
0480 
0481 /**
0482   * @brief  DeInitialize the HASH MSP.
0483   * @param  hhash HASH handle.
0484   * @retval None
0485   */
0486 __weak void HAL_HASH_MspDeInit(HASH_HandleTypeDef *hhash)
0487 {
0488   /* Prevent unused argument(s) compilation warning */
0489   UNUSED(hhash);
0490 
0491   /* NOTE : This function should not be modified; when the callback is needed,
0492             HAL_HASH_MspDeInit() can be implemented in the user file.
0493    */
0494 }
0495 
0496 /**
0497   * @brief  Input data transfer complete call back.
0498   * @note   HAL_HASH_InCpltCallback() is called when the complete input message
0499   *         has been fed to the Peripheral. This API is invoked only when input data are
0500   *         entered under interruption or through DMA.
0501   * @note   In case of HASH or HMAC multi-buffer DMA feeding case (MDMAT bit set),
0502   *         HAL_HASH_InCpltCallback() is called at the end of each buffer feeding
0503   *         to the Peripheral.
0504   * @param  hhash HASH handle.
0505   * @retval None
0506   */
0507 __weak void HAL_HASH_InCpltCallback(HASH_HandleTypeDef *hhash)
0508 {
0509   /* Prevent unused argument(s) compilation warning */
0510   UNUSED(hhash);
0511 
0512   /* NOTE : This function should not be modified; when the callback is needed,
0513             HAL_HASH_InCpltCallback() can be implemented in the user file.
0514    */
0515 }
0516 
0517 /**
0518   * @brief  Digest computation complete call back.
0519   * @note   HAL_HASH_DgstCpltCallback() is used under interruption, is not
0520   *         relevant with DMA.
0521   * @param  hhash HASH handle.
0522   * @retval None
0523   */
0524 __weak void HAL_HASH_DgstCpltCallback(HASH_HandleTypeDef *hhash)
0525 {
0526   /* Prevent unused argument(s) compilation warning */
0527   UNUSED(hhash);
0528 
0529   /* NOTE : This function should not be modified; when the callback is needed,
0530             HAL_HASH_DgstCpltCallback() can be implemented in the user file.
0531    */
0532 }
0533 
0534 /**
0535   * @brief  Error callback.
0536   * @note   Code user can resort to hhash->Status (HAL_ERROR, HAL_TIMEOUT,...)
0537   *         to retrieve the error type.
0538   * @param  hhash HASH handle.
0539   * @retval None
0540   */
0541 __weak void HAL_HASH_ErrorCallback(HASH_HandleTypeDef *hhash)
0542 {
0543   /* Prevent unused argument(s) compilation warning */
0544   UNUSED(hhash);
0545 
0546   /* NOTE : This function should not be modified; when the callback is needed,
0547             HAL_HASH_ErrorCallback() can be implemented in the user file.
0548    */
0549 }
0550 
0551 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
0552 /**
0553   * @brief  Register a User HASH Callback
0554   *         To be used instead of the weak (surcharged) predefined callback
0555   * @param hhash HASH handle
0556   * @param CallbackID ID of the callback to be registered
0557   *        This parameter can be one of the following values:
0558   *          @arg @ref HAL_HASH_INPUTCPLT_CB_ID HASH input completion Callback ID
0559   *          @arg @ref HAL_HASH_DGSTCPLT_CB_ID HASH digest computation completion Callback ID
0560   *          @arg @ref HAL_HASH_ERROR_CB_ID HASH error Callback ID
0561   *          @arg @ref HAL_HASH_MSPINIT_CB_ID HASH MspInit callback ID
0562   *          @arg @ref HAL_HASH_MSPDEINIT_CB_ID HASH MspDeInit callback ID
0563   * @param pCallback pointer to the Callback function
0564   * @retval status
0565   */
0566 HAL_StatusTypeDef HAL_HASH_RegisterCallback(HASH_HandleTypeDef *hhash, HAL_HASH_CallbackIDTypeDef CallbackID,
0567                                             pHASH_CallbackTypeDef pCallback)
0568 {
0569   HAL_StatusTypeDef status = HAL_OK;
0570 
0571   if (pCallback == NULL)
0572   {
0573     /* Update the error code */
0574     hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
0575     return HAL_ERROR;
0576   }
0577   /* Process locked */
0578   __HAL_LOCK(hhash);
0579 
0580   if (HAL_HASH_STATE_READY == hhash->State)
0581   {
0582     switch (CallbackID)
0583     {
0584       case HAL_HASH_INPUTCPLT_CB_ID :
0585         hhash->InCpltCallback = pCallback;
0586         break;
0587 
0588       case HAL_HASH_DGSTCPLT_CB_ID :
0589         hhash->DgstCpltCallback = pCallback;
0590         break;
0591 
0592       case HAL_HASH_ERROR_CB_ID :
0593         hhash->ErrorCallback = pCallback;
0594         break;
0595 
0596       case HAL_HASH_MSPINIT_CB_ID :
0597         hhash->MspInitCallback = pCallback;
0598         break;
0599 
0600       case HAL_HASH_MSPDEINIT_CB_ID :
0601         hhash->MspDeInitCallback = pCallback;
0602         break;
0603 
0604       default :
0605         /* Update the error code */
0606         hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
0607         /* update return status */
0608         status =  HAL_ERROR;
0609         break;
0610     }
0611   }
0612   else if (HAL_HASH_STATE_RESET == hhash->State)
0613   {
0614     switch (CallbackID)
0615     {
0616       case HAL_HASH_MSPINIT_CB_ID :
0617         hhash->MspInitCallback = pCallback;
0618         break;
0619 
0620       case HAL_HASH_MSPDEINIT_CB_ID :
0621         hhash->MspDeInitCallback = pCallback;
0622         break;
0623 
0624       default :
0625         /* Update the error code */
0626         hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
0627         /* update return status */
0628         status =  HAL_ERROR;
0629         break;
0630     }
0631   }
0632   else
0633   {
0634     /* Update the error code */
0635     hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
0636     /* update return status */
0637     status =  HAL_ERROR;
0638   }
0639 
0640   /* Release Lock */
0641   __HAL_UNLOCK(hhash);
0642   return status;
0643 }
0644 
0645 /**
0646   * @brief  Unregister a HASH Callback
0647   *         HASH Callback is redirected to the weak (surcharged) predefined callback
0648   * @param hhash HASH handle
0649   * @param CallbackID ID of the callback to be unregistered
0650   *        This parameter can be one of the following values:
0651   *          @arg @ref HAL_HASH_INPUTCPLT_CB_ID HASH input completion Callback ID
0652   *          @arg @ref HAL_HASH_DGSTCPLT_CB_ID HASH digest computation completion Callback ID
0653   *          @arg @ref HAL_HASH_ERROR_CB_ID HASH error Callback ID
0654   *          @arg @ref HAL_HASH_MSPINIT_CB_ID HASH MspInit callback ID
0655   *          @arg @ref HAL_HASH_MSPDEINIT_CB_ID HASH MspDeInit callback ID
0656   * @retval status
0657   */
0658 HAL_StatusTypeDef HAL_HASH_UnRegisterCallback(HASH_HandleTypeDef *hhash, HAL_HASH_CallbackIDTypeDef CallbackID)
0659 {
0660   HAL_StatusTypeDef status = HAL_OK;
0661 
0662   /* Process locked */
0663   __HAL_LOCK(hhash);
0664 
0665   if (HAL_HASH_STATE_READY == hhash->State)
0666   {
0667     switch (CallbackID)
0668     {
0669       case HAL_HASH_INPUTCPLT_CB_ID :
0670         hhash->InCpltCallback = HAL_HASH_InCpltCallback;     /* Legacy weak (surcharged) input completion callback */
0671         break;
0672 
0673       case HAL_HASH_DGSTCPLT_CB_ID :
0674         hhash->DgstCpltCallback = HAL_HASH_DgstCpltCallback; /* Legacy weak (surcharged) digest computation
0675                                                                 completion callback */
0676         break;
0677 
0678       case HAL_HASH_ERROR_CB_ID :
0679         hhash->ErrorCallback = HAL_HASH_ErrorCallback;       /* Legacy weak (surcharged) error callback */
0680         break;
0681 
0682       case HAL_HASH_MSPINIT_CB_ID :
0683         hhash->MspInitCallback = HAL_HASH_MspInit;           /* Legacy weak (surcharged) Msp Init */
0684         break;
0685 
0686       case HAL_HASH_MSPDEINIT_CB_ID :
0687         hhash->MspDeInitCallback = HAL_HASH_MspDeInit;       /* Legacy weak (surcharged) Msp DeInit */
0688         break;
0689 
0690       default :
0691         /* Update the error code */
0692         hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
0693         /* update return status */
0694         status =  HAL_ERROR;
0695         break;
0696     }
0697   }
0698   else if (HAL_HASH_STATE_RESET == hhash->State)
0699   {
0700     switch (CallbackID)
0701     {
0702       case HAL_HASH_MSPINIT_CB_ID :
0703         hhash->MspInitCallback = HAL_HASH_MspInit;           /* Legacy weak (surcharged) Msp Init */
0704         break;
0705 
0706       case HAL_HASH_MSPDEINIT_CB_ID :
0707         hhash->MspDeInitCallback = HAL_HASH_MspDeInit;       /* Legacy weak (surcharged) Msp DeInit */
0708         break;
0709 
0710       default :
0711         /* Update the error code */
0712         hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
0713         /* update return status */
0714         status =  HAL_ERROR;
0715         break;
0716     }
0717   }
0718   else
0719   {
0720     /* Update the error code */
0721     hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
0722     /* update return status */
0723     status =  HAL_ERROR;
0724   }
0725 
0726   /* Release Lock */
0727   __HAL_UNLOCK(hhash);
0728   return status;
0729 }
0730 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
0731 
0732 /**
0733   * @}
0734   */
0735 
0736 /** @defgroup HASH_Exported_Functions_Group2 HASH processing functions in polling mode
0737   * @ingroup RTEMSBSPsARMSTM32H7
0738   *  @brief   HASH processing functions using polling mode.
0739   *
0740 @verbatim
0741  ===============================================================================
0742                  ##### Polling mode HASH processing functions #####
0743  ===============================================================================
0744     [..]  This section provides functions allowing to calculate in polling mode
0745           the hash value using one of the following algorithms:
0746       (+) MD5
0747          (++) HAL_HASH_MD5_Start()
0748          (++) HAL_HASH_MD5_Accmlt()
0749          (++) HAL_HASH_MD5_Accmlt_End()
0750       (+) SHA1
0751          (++) HAL_HASH_SHA1_Start()
0752          (++) HAL_HASH_SHA1_Accmlt()
0753          (++) HAL_HASH_SHA1_Accmlt_End()
0754 
0755     [..] For a single buffer to be hashed, user can resort to HAL_HASH_xxx_Start().
0756 
0757     [..]  In case of multi-buffer HASH processing (a single digest is computed while
0758           several buffers are fed to the Peripheral), the user can resort to successive calls
0759           to HAL_HASH_xxx_Accumulate() and wrap-up the digest computation by a call
0760           to HAL_HASH_xxx_Accumulate_End().
0761 
0762 @endverbatim
0763   * @{
0764   */
0765 
0766 /**
0767   * @brief  Initialize the HASH peripheral in MD5 mode, next process pInBuffer then
0768   *         read the computed digest.
0769   * @note   Digest is available in pOutBuffer.
0770   * @param  hhash HASH handle.
0771   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
0772   * @param  Size length of the input buffer in bytes.
0773   * @param  pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
0774   * @param  Timeout Timeout value
0775   * @retval HAL status
0776   */
0777 HAL_StatusTypeDef HAL_HASH_MD5_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer,
0778                                      uint32_t Timeout)
0779 {
0780   return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_MD5);
0781 }
0782 
0783 /**
0784   * @brief  If not already done, initialize the HASH peripheral in MD5 mode then
0785   *         processes pInBuffer.
0786   * @note   Consecutive calls to HAL_HASH_MD5_Accmlt() can be used to feed
0787   *         several input buffers back-to-back to the Peripheral that will yield a single
0788   *         HASH signature once all buffers have been entered. Wrap-up of input
0789   *         buffers feeding and retrieval of digest is done by a call to
0790   *         HAL_HASH_MD5_Accmlt_End().
0791   * @note   Field hhash->Phase of HASH handle is tested to check whether or not
0792   *         the Peripheral has already been initialized.
0793   * @note   Digest is not retrieved by this API, user must resort to HAL_HASH_MD5_Accmlt_End()
0794   *         to read it, feeding at the same time the last input buffer to the Peripheral.
0795   * @note   The input buffer size (in bytes) must be a multiple of 4 otherwise, the
0796   *         HASH digest computation is corrupted. Only HAL_HASH_MD5_Accmlt_End() is able
0797   *         to manage the ending buffer with a length in bytes not a multiple of 4.
0798   * @param  hhash HASH handle.
0799   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
0800   * @param  Size length of the input buffer in bytes, must be a multiple of 4.
0801   * @retval HAL status
0802   */
0803 HAL_StatusTypeDef HAL_HASH_MD5_Accmlt(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
0804 {
0805   return  HASH_Accumulate(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5);
0806 }
0807 
0808 /**
0809   * @brief  End computation of a single HASH signature after several calls to HAL_HASH_MD5_Accmlt() API.
0810   * @note   Digest is available in pOutBuffer.
0811   * @param  hhash HASH handle.
0812   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
0813   * @param  Size length of the input buffer in bytes.
0814   * @param  pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
0815   * @param  Timeout Timeout value
0816   * @retval HAL status
0817   */
0818 HAL_StatusTypeDef HAL_HASH_MD5_Accmlt_End(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size,
0819                                           uint8_t *pOutBuffer, uint32_t Timeout)
0820 {
0821   return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_MD5);
0822 }
0823 
0824 /**
0825   * @brief  Initialize the HASH peripheral in SHA1 mode, next process pInBuffer then
0826   *         read the computed digest.
0827   * @note   Digest is available in pOutBuffer.
0828   * @param  hhash HASH handle.
0829   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
0830   * @param  Size length of the input buffer in bytes.
0831   * @param  pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
0832   * @param  Timeout Timeout value
0833   * @retval HAL status
0834   */
0835 HAL_StatusTypeDef HAL_HASH_SHA1_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer,
0836                                       uint32_t Timeout)
0837 {
0838   return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA1);
0839 }
0840 
0841 /**
0842   * @brief  If not already done, initialize the HASH peripheral in SHA1 mode then
0843   *         processes pInBuffer.
0844   * @note   Consecutive calls to HAL_HASH_SHA1_Accmlt() can be used to feed
0845   *         several input buffers back-to-back to the Peripheral that will yield a single
0846   *         HASH signature once all buffers have been entered. Wrap-up of input
0847   *         buffers feeding and retrieval of digest is done by a call to
0848   *         HAL_HASH_SHA1_Accmlt_End().
0849   * @note   Field hhash->Phase of HASH handle is tested to check whether or not
0850   *         the Peripheral has already been initialized.
0851   * @note   Digest is not retrieved by this API, user must resort to HAL_HASH_SHA1_Accmlt_End()
0852   *         to read it, feeding at the same time the last input buffer to the Peripheral.
0853   * @note   The input buffer size (in bytes) must be a multiple of 4 otherwise, the
0854   *         HASH digest computation is corrupted. Only HAL_HASH_SHA1_Accmlt_End() is able
0855   *         to manage the ending buffer with a length in bytes not a multiple of 4.
0856   * @param  hhash HASH handle.
0857   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
0858   * @param  Size length of the input buffer in bytes, must be a multiple of 4.
0859   * @retval HAL status
0860   */
0861 HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
0862 {
0863   return  HASH_Accumulate(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1);
0864 }
0865 
0866 /**
0867   * @brief  End computation of a single HASH signature after several calls to HAL_HASH_SHA1_Accmlt() API.
0868   * @note   Digest is available in pOutBuffer.
0869   * @param  hhash HASH handle.
0870   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
0871   * @param  Size length of the input buffer in bytes.
0872   * @param  pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
0873   * @param  Timeout Timeout value
0874   * @retval HAL status
0875   */
0876 HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt_End(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size,
0877                                            uint8_t *pOutBuffer, uint32_t Timeout)
0878 {
0879   return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA1);
0880 }
0881 
0882 /**
0883   * @}
0884   */
0885 
0886 /** @defgroup HASH_Exported_Functions_Group3 HASH processing functions in interrupt mode
0887   * @ingroup RTEMSBSPsARMSTM32H7
0888   *  @brief   HASH processing functions using interrupt mode.
0889   *
0890 @verbatim
0891  ===============================================================================
0892                  ##### Interruption mode HASH processing functions #####
0893  ===============================================================================
0894     [..]  This section provides functions allowing to calculate in interrupt mode
0895           the hash value using one of the following algorithms:
0896       (+) MD5
0897          (++) HAL_HASH_MD5_Start_IT()
0898          (++) HAL_HASH_MD5_Accmlt_IT()
0899          (++) HAL_HASH_MD5_Accmlt_End_IT()
0900       (+) SHA1
0901          (++) HAL_HASH_SHA1_Start_IT()
0902          (++) HAL_HASH_SHA1_Accmlt_IT()
0903          (++) HAL_HASH_SHA1_Accmlt_End_IT()
0904 
0905     [..]  API HAL_HASH_IRQHandler() manages each HASH interruption.
0906 
0907     [..] Note that HAL_HASH_IRQHandler() manages as well HASH Peripheral interruptions when in
0908          HMAC processing mode.
0909 
0910 
0911 @endverbatim
0912   * @{
0913   */
0914 
0915 /**
0916   * @brief  Initialize the HASH peripheral in MD5 mode, next process pInBuffer then
0917   *         read the computed digest in interruption mode.
0918   * @note   Digest is available in pOutBuffer.
0919   * @param  hhash HASH handle.
0920   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
0921   * @param  Size length of the input buffer in bytes.
0922   * @param  pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
0923   * @retval HAL status
0924   */
0925 HAL_StatusTypeDef HAL_HASH_MD5_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size,
0926                                         uint8_t *pOutBuffer)
0927 {
0928   return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_MD5);
0929 }
0930 
0931 /**
0932   * @brief  If not already done, initialize the HASH peripheral in MD5 mode then
0933   *         processes pInBuffer in interruption mode.
0934   * @note   Consecutive calls to HAL_HASH_MD5_Accmlt_IT() can be used to feed
0935   *         several input buffers back-to-back to the Peripheral that will yield a single
0936   *         HASH signature once all buffers have been entered. Wrap-up of input
0937   *         buffers feeding and retrieval of digest is done by a call to
0938   *         HAL_HASH_MD5_Accmlt_End_IT().
0939   * @note   Field hhash->Phase of HASH handle is tested to check whether or not
0940   *         the Peripheral has already been initialized.
0941   * @note   The input buffer size (in bytes) must be a multiple of 4 otherwise, the
0942   *         HASH digest computation is corrupted. Only HAL_HASH_MD5_Accmlt_End_IT() is able
0943   *         to manage the ending buffer with a length in bytes not a multiple of 4.
0944   * @param  hhash HASH handle.
0945   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
0946   * @param  Size length of the input buffer in bytes, must be a multiple of 4.
0947   * @retval HAL status
0948   */
0949 HAL_StatusTypeDef HAL_HASH_MD5_Accmlt_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
0950 {
0951   return  HASH_Accumulate_IT(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5);
0952 }
0953 
0954 /**
0955   * @brief  End computation of a single HASH signature after several calls to HAL_HASH_MD5_Accmlt_IT() API.
0956   * @note   Digest is available in pOutBuffer.
0957   * @param  hhash HASH handle.
0958   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
0959   * @param  Size length of the input buffer in bytes.
0960   * @param  pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
0961   * @retval HAL status
0962   */
0963 HAL_StatusTypeDef HAL_HASH_MD5_Accmlt_End_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size,
0964                                              uint8_t *pOutBuffer)
0965 {
0966   return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_MD5);
0967 }
0968 
0969 /**
0970   * @brief  Initialize the HASH peripheral in SHA1 mode, next process pInBuffer then
0971   *         read the computed digest in interruption mode.
0972   * @note   Digest is available in pOutBuffer.
0973   * @param  hhash HASH handle.
0974   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
0975   * @param  Size length of the input buffer in bytes.
0976   * @param  pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
0977   * @retval HAL status
0978   */
0979 HAL_StatusTypeDef HAL_HASH_SHA1_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size,
0980                                          uint8_t *pOutBuffer)
0981 {
0982   return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_SHA1);
0983 }
0984 
0985 
0986 /**
0987   * @brief  If not already done, initialize the HASH peripheral in SHA1 mode then
0988   *         processes pInBuffer in interruption mode.
0989   * @note   Consecutive calls to HAL_HASH_SHA1_Accmlt_IT() can be used to feed
0990   *         several input buffers back-to-back to the Peripheral that will yield a single
0991   *         HASH signature once all buffers have been entered. Wrap-up of input
0992   *         buffers feeding and retrieval of digest is done by a call to
0993   *         HAL_HASH_SHA1_Accmlt_End_IT().
0994   * @note   Field hhash->Phase of HASH handle is tested to check whether or not
0995   *         the Peripheral has already been initialized.
0996   * @note   The input buffer size (in bytes) must be a multiple of 4 otherwise, the
0997   *         HASH digest computation is corrupted. Only HAL_HASH_SHA1_Accmlt_End_IT() is able
0998   *         to manage the ending buffer with a length in bytes not a multiple of 4.
0999   * @param  hhash HASH handle.
1000   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
1001   * @param  Size length of the input buffer in bytes, must be a multiple of 4.
1002   * @retval HAL status
1003   */
1004 HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
1005 {
1006   return  HASH_Accumulate_IT(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1);
1007 }
1008 
1009 /**
1010   * @brief  End computation of a single HASH signature after several calls to HAL_HASH_SHA1_Accmlt_IT() API.
1011   * @note   Digest is available in pOutBuffer.
1012   * @param  hhash HASH handle.
1013   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
1014   * @param  Size length of the input buffer in bytes.
1015   * @param  pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
1016   * @retval HAL status
1017   */
1018 HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt_End_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size,
1019                                               uint8_t *pOutBuffer)
1020 {
1021   return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_SHA1);
1022 }
1023 
1024 /**
1025   * @brief Handle HASH interrupt request.
1026   * @param hhash HASH handle.
1027   * @note  HAL_HASH_IRQHandler() handles interrupts in HMAC processing as well.
1028   * @note  In case of error reported during the HASH interruption processing,
1029   *        HAL_HASH_ErrorCallback() API is called so that user code can
1030   *        manage the error. The error type is available in hhash->Status field.
1031   * @retval None
1032   */
1033 void HAL_HASH_IRQHandler(HASH_HandleTypeDef *hhash)
1034 {
1035   hhash->Status = HASH_IT(hhash);
1036   if (hhash->Status != HAL_OK)
1037   {
1038     hhash->ErrorCode |= HAL_HASH_ERROR_IT;
1039 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
1040     hhash->ErrorCallback(hhash);
1041 #else
1042     HAL_HASH_ErrorCallback(hhash);
1043 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
1044     /* After error handling by code user, reset HASH handle HAL status */
1045     hhash->Status = HAL_OK;
1046   }
1047 }
1048 
1049 /**
1050   * @}
1051   */
1052 
1053 /** @defgroup HASH_Exported_Functions_Group4 HASH processing functions in DMA mode
1054   * @ingroup RTEMSBSPsARMSTM32H7
1055   *  @brief   HASH processing functions using DMA mode.
1056   *
1057 @verbatim
1058  ===============================================================================
1059                     ##### DMA mode HASH processing functions #####
1060  ===============================================================================
1061     [..]  This section provides functions allowing to calculate in DMA mode
1062           the hash value using one of the following algorithms:
1063       (+) MD5
1064          (++) HAL_HASH_MD5_Start_DMA()
1065          (++) HAL_HASH_MD5_Finish()
1066       (+) SHA1
1067          (++) HAL_HASH_SHA1_Start_DMA()
1068          (++) HAL_HASH_SHA1_Finish()
1069 
1070     [..]  When resorting to DMA mode to enter the data in the Peripheral, user must resort
1071           to  HAL_HASH_xxx_Start_DMA() then read the resulting digest with
1072           HAL_HASH_xxx_Finish().
1073     [..]  In case of multi-buffer HASH processing, MDMAT bit must first be set before
1074           the successive calls to HAL_HASH_xxx_Start_DMA(). Then, MDMAT bit needs to be
1075           reset before the last call to HAL_HASH_xxx_Start_DMA(). Digest is finally
1076           retrieved thanks to HAL_HASH_xxx_Finish().
1077 
1078 @endverbatim
1079   * @{
1080   */
1081 
1082 /**
1083   * @brief  Initialize the HASH peripheral in MD5 mode then initiate a DMA transfer
1084   *         to feed the input buffer to the Peripheral.
1085   * @note   Once the DMA transfer is finished, HAL_HASH_MD5_Finish() API must
1086   *         be called to retrieve the computed digest.
1087   * @param  hhash HASH handle.
1088   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
1089   * @param  Size length of the input buffer in bytes.
1090   * @retval HAL status
1091   */
1092 HAL_StatusTypeDef HAL_HASH_MD5_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
1093 {
1094   return HASH_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5);
1095 }
1096 
1097 /**
1098   * @brief  Return the computed digest in MD5 mode.
1099   * @note   The API waits for DCIS to be set then reads the computed digest.
1100   * @note   HAL_HASH_MD5_Finish() can be used as well to retrieve the digest in
1101   *         HMAC MD5 mode.
1102   * @param  hhash HASH handle.
1103   * @param  pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
1104   * @param  Timeout Timeout value.
1105   * @retval HAL status
1106   */
1107 HAL_StatusTypeDef HAL_HASH_MD5_Finish(HASH_HandleTypeDef *hhash, uint8_t *pOutBuffer, uint32_t Timeout)
1108 {
1109   return HASH_Finish(hhash, pOutBuffer, Timeout);
1110 }
1111 
1112 /**
1113   * @brief  Initialize the HASH peripheral in SHA1 mode then initiate a DMA transfer
1114   *         to feed the input buffer to the Peripheral.
1115   * @note   Once the DMA transfer is finished, HAL_HASH_SHA1_Finish() API must
1116   *         be called to retrieve the computed digest.
1117   * @param  hhash HASH handle.
1118   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
1119   * @param  Size length of the input buffer in bytes.
1120   * @retval HAL status
1121   */
1122 HAL_StatusTypeDef HAL_HASH_SHA1_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
1123 {
1124   return HASH_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1);
1125 }
1126 
1127 
1128 /**
1129   * @brief  Return the computed digest in SHA1 mode.
1130   * @note   The API waits for DCIS to be set then reads the computed digest.
1131   * @note   HAL_HASH_SHA1_Finish() can be used as well to retrieve the digest in
1132   *         HMAC SHA1 mode.
1133   * @param  hhash HASH handle.
1134   * @param  pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
1135   * @param  Timeout Timeout value.
1136   * @retval HAL status
1137   */
1138 HAL_StatusTypeDef HAL_HASH_SHA1_Finish(HASH_HandleTypeDef *hhash, uint8_t *pOutBuffer, uint32_t Timeout)
1139 {
1140   return HASH_Finish(hhash, pOutBuffer, Timeout);
1141 }
1142 
1143 /**
1144   * @}
1145   */
1146 
1147 /** @defgroup HASH_Exported_Functions_Group5 HMAC processing functions in polling mode
1148   * @ingroup RTEMSBSPsARMSTM32H7
1149   *  @brief   HMAC processing functions using polling mode.
1150   *
1151 @verbatim
1152  ===============================================================================
1153                  ##### Polling mode HMAC processing functions #####
1154  ===============================================================================
1155     [..]  This section provides functions allowing to calculate in polling mode
1156           the HMAC value using one of the following algorithms:
1157       (+) MD5
1158          (++) HAL_HMAC_MD5_Start()
1159       (+) SHA1
1160          (++) HAL_HMAC_SHA1_Start()
1161 
1162 
1163 @endverbatim
1164   * @{
1165   */
1166 
1167 /**
1168   * @brief  Initialize the HASH peripheral in HMAC MD5 mode, next process pInBuffer then
1169   *         read the computed digest.
1170   * @note   Digest is available in pOutBuffer.
1171   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
1172   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
1173   * @param  hhash HASH handle.
1174   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
1175   * @param  Size length of the input buffer in bytes.
1176   * @param  pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
1177   * @param  Timeout Timeout value.
1178   * @retval HAL status
1179   */
1180 HAL_StatusTypeDef HAL_HMAC_MD5_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer,
1181                                      uint32_t Timeout)
1182 {
1183   return HMAC_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_MD5);
1184 }
1185 
1186 /**
1187   * @brief  Initialize the HASH peripheral in HMAC SHA1 mode, next process pInBuffer then
1188   *         read the computed digest.
1189   * @note   Digest is available in pOutBuffer.
1190   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
1191   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
1192   * @param  hhash HASH handle.
1193   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
1194   * @param  Size length of the input buffer in bytes.
1195   * @param  pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
1196   * @param  Timeout Timeout value.
1197   * @retval HAL status
1198   */
1199 HAL_StatusTypeDef HAL_HMAC_SHA1_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer,
1200                                       uint32_t Timeout)
1201 {
1202   return HMAC_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA1);
1203 }
1204 
1205 /**
1206   * @}
1207   */
1208 
1209 
1210 /** @defgroup HASH_Exported_Functions_Group6 HMAC processing functions in interrupt mode
1211   * @ingroup RTEMSBSPsARMSTM32H7
1212   *  @brief   HMAC processing functions using interrupt mode.
1213   *
1214 @verbatim
1215  ===============================================================================
1216                  ##### Interrupt mode HMAC processing functions #####
1217  ===============================================================================
1218     [..]  This section provides functions allowing to calculate in interrupt mode
1219           the HMAC value using one of the following algorithms:
1220       (+) MD5
1221          (++) HAL_HMAC_MD5_Start_IT()
1222       (+) SHA1
1223          (++) HAL_HMAC_SHA1_Start_IT()
1224 
1225 @endverbatim
1226   * @{
1227   */
1228 
1229 
1230 /**
1231   * @brief  Initialize the HASH peripheral in HMAC MD5 mode, next process pInBuffer then
1232   *         read the computed digest in interrupt mode.
1233   * @note   Digest is available in pOutBuffer.
1234   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
1235   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
1236   * @param  hhash HASH handle.
1237   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
1238   * @param  Size length of the input buffer in bytes.
1239   * @param  pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
1240   * @retval HAL status
1241   */
1242 HAL_StatusTypeDef HAL_HMAC_MD5_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size,
1243                                         uint8_t *pOutBuffer)
1244 {
1245   return  HMAC_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_MD5);
1246 }
1247 
1248 /**
1249   * @brief  Initialize the HASH peripheral in HMAC SHA1 mode, next process pInBuffer then
1250   *         read the computed digest in interrupt mode.
1251   * @note   Digest is available in pOutBuffer.
1252   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
1253   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
1254   * @param  hhash HASH handle.
1255   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
1256   * @param  Size length of the input buffer in bytes.
1257   * @param  pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
1258   * @retval HAL status
1259   */
1260 HAL_StatusTypeDef HAL_HMAC_SHA1_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size,
1261                                          uint8_t *pOutBuffer)
1262 {
1263   return  HMAC_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_SHA1);
1264 }
1265 
1266 /**
1267   * @}
1268   */
1269 
1270 
1271 
1272 /** @defgroup HASH_Exported_Functions_Group7 HMAC processing functions in DMA mode
1273   * @ingroup RTEMSBSPsARMSTM32H7
1274   *  @brief   HMAC processing functions using DMA modes.
1275   *
1276 @verbatim
1277  ===============================================================================
1278                  ##### DMA mode HMAC processing functions #####
1279  ===============================================================================
1280     [..]  This section provides functions allowing to calculate in DMA mode
1281           the HMAC value using one of the following algorithms:
1282       (+) MD5
1283          (++) HAL_HMAC_MD5_Start_DMA()
1284       (+) SHA1
1285          (++) HAL_HMAC_SHA1_Start_DMA()
1286 
1287     [..]  When resorting to DMA mode to enter the data in the Peripheral for HMAC processing,
1288           user must resort to  HAL_HMAC_xxx_Start_DMA() then read the resulting digest
1289           with HAL_HASH_xxx_Finish().
1290 
1291 @endverbatim
1292   * @{
1293   */
1294 
1295 
1296 /**
1297   * @brief  Initialize the HASH peripheral in HMAC MD5 mode then initiate the required
1298   *         DMA transfers to feed the key and the input buffer to the Peripheral.
1299   * @note   Once the DMA transfers are finished (indicated by hhash->State set back
1300   *         to HAL_HASH_STATE_READY), HAL_HASH_MD5_Finish() API must be called to retrieve
1301   *         the computed digest.
1302   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
1303   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
1304   * @note   If MDMAT bit is set before calling this function (multi-buffer
1305   *          HASH processing case), the input buffer size (in bytes) must be
1306   *          a multiple of 4 otherwise, the HASH digest computation is corrupted.
1307   *          For the processing of the last buffer of the thread, MDMAT bit must
1308   *          be reset and the buffer length (in bytes) doesn't have to be a
1309   *          multiple of 4.
1310   * @param  hhash HASH handle.
1311   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
1312   * @param  Size length of the input buffer in bytes.
1313   * @retval HAL status
1314   */
1315 HAL_StatusTypeDef HAL_HMAC_MD5_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
1316 {
1317   return  HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5);
1318 }
1319 
1320 
1321 /**
1322   * @brief  Initialize the HASH peripheral in HMAC SHA1 mode then initiate the required
1323   *         DMA transfers to feed the key and the input buffer to the Peripheral.
1324   * @note   Once the DMA transfers are finished (indicated by hhash->State set back
1325   *         to HAL_HASH_STATE_READY), HAL_HASH_SHA1_Finish() API must be called to retrieve
1326   *         the computed digest.
1327   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
1328   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
1329   * @note   If MDMAT bit is set before calling this function (multi-buffer
1330   *          HASH processing case), the input buffer size (in bytes) must be
1331   *          a multiple of 4 otherwise, the HASH digest computation is corrupted.
1332   *          For the processing of the last buffer of the thread, MDMAT bit must
1333   *          be reset and the buffer length (in bytes) doesn't have to be a
1334   *          multiple of 4.
1335   * @param  hhash HASH handle.
1336   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
1337   * @param  Size length of the input buffer in bytes.
1338   * @retval HAL status
1339   */
1340 HAL_StatusTypeDef HAL_HMAC_SHA1_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
1341 {
1342   return  HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1);
1343 }
1344 
1345 /**
1346   * @}
1347   */
1348 
1349 /** @defgroup HASH_Exported_Functions_Group8 Peripheral states functions
1350   * @ingroup RTEMSBSPsARMSTM32H7
1351   *  @brief   Peripheral State functions.
1352   *
1353 @verbatim
1354  ===============================================================================
1355                       ##### Peripheral State methods #####
1356  ===============================================================================
1357     [..]
1358     This section permits to get in run-time the state and the peripheral handle
1359     status of the peripheral:
1360       (+) HAL_HASH_GetState()
1361       (+) HAL_HASH_GetStatus()
1362 
1363     [..]
1364     Additionally, this subsection provides functions allowing to save and restore
1365     the HASH or HMAC processing context in case of calculation suspension:
1366       (+) HAL_HASH_ContextSaving()
1367       (+) HAL_HASH_ContextRestoring()
1368 
1369     [..]
1370     This subsection provides functions allowing to suspend the HASH processing
1371       (+) when input are fed to the Peripheral by software
1372           (++) HAL_HASH_SwFeed_ProcessSuspend()
1373       (+) when input are fed to the Peripheral by DMA
1374           (++) HAL_HASH_DMAFeed_ProcessSuspend()
1375 
1376 
1377 
1378 @endverbatim
1379   * @{
1380   */
1381 
1382 /**
1383   * @brief  Return the HASH handle state.
1384   * @note   The API yields the current state of the handle (BUSY, READY,...).
1385   * @param  hhash HASH handle.
1386   * @retval HAL HASH state
1387   */
1388 HAL_HASH_StateTypeDef HAL_HASH_GetState(HASH_HandleTypeDef *hhash)
1389 {
1390   return hhash->State;
1391 }
1392 
1393 
1394 /**
1395   * @brief Return the HASH HAL status.
1396   * @note  The API yields the HAL status of the handle: it is the result of the
1397   *        latest HASH processing and allows to report any issue (e.g. HAL_TIMEOUT).
1398   * @param  hhash HASH handle.
1399   * @retval HAL status
1400   */
1401 HAL_StatusTypeDef HAL_HASH_GetStatus(HASH_HandleTypeDef *hhash)
1402 {
1403   return hhash->Status;
1404 }
1405 
1406 /**
1407   * @brief  Save the HASH context in case of processing suspension.
1408   * @param  hhash HASH handle.
1409   * @param  pMemBuffer pointer to the memory buffer where the HASH context
1410   *         is saved.
1411   * @note   The IMR, STR, CR then all the CSR registers are saved
1412   *         in that order. Only the r/w bits are read to be restored later on.
1413   * @note   By default, all the context swap registers (there are
1414   *         HASH_NUMBER_OF_CSR_REGISTERS of those) are saved.
1415   * @note   pMemBuffer points to a buffer allocated by the user. The buffer size
1416   *         must be at least (HASH_NUMBER_OF_CSR_REGISTERS + 3) * 4 uint8 long.
1417   * @retval None
1418   */
1419 void HAL_HASH_ContextSaving(HASH_HandleTypeDef *hhash, uint8_t *pMemBuffer)
1420 {
1421   uint32_t mem_ptr = (uint32_t)pMemBuffer;
1422   uint32_t csr_ptr = (uint32_t)HASH->CSR;
1423   uint32_t i;
1424 
1425   /* Prevent unused argument(s) compilation warning */
1426   UNUSED(hhash);
1427 
1428   /* Save IMR register content */
1429   *(uint32_t *)(mem_ptr) = READ_BIT(HASH->IMR, HASH_IT_DINI | HASH_IT_DCI);
1430   mem_ptr += 4U;
1431   /* Save STR register content */
1432   *(uint32_t *)(mem_ptr) = READ_BIT(HASH->STR, HASH_STR_NBLW);
1433   mem_ptr += 4U;
1434   /* Save CR register content */
1435   *(uint32_t *)(mem_ptr) = READ_BIT(HASH->CR, HASH_CR_DMAE | HASH_CR_DATATYPE | HASH_CR_MODE | HASH_CR_ALGO |
1436                                     HASH_CR_LKEY | HASH_CR_MDMAT);
1437   mem_ptr += 4U;
1438   /* By default, save all CSRs registers */
1439   for (i = HASH_NUMBER_OF_CSR_REGISTERS; i > 0U; i--)
1440   {
1441     *(uint32_t *)(mem_ptr) = *(uint32_t *)(csr_ptr);
1442     mem_ptr += 4U;
1443     csr_ptr += 4U;
1444   }
1445 }
1446 
1447 
1448 /**
1449   * @brief  Restore the HASH context in case of processing resumption.
1450   * @param  hhash HASH handle.
1451   * @param  pMemBuffer pointer to the memory buffer where the HASH context
1452   *         is stored.
1453   * @note   The IMR, STR, CR then all the CSR registers are restored
1454   *         in that order. Only the r/w bits are restored.
1455   * @note   By default, all the context swap registers (HASH_NUMBER_OF_CSR_REGISTERS
1456   *         of those) are restored (all of them have been saved by default
1457   *         beforehand).
1458   * @retval None
1459   */
1460 void HAL_HASH_ContextRestoring(HASH_HandleTypeDef *hhash, uint8_t *pMemBuffer)
1461 {
1462   uint32_t mem_ptr = (uint32_t)pMemBuffer;
1463   uint32_t csr_ptr = (uint32_t)HASH->CSR;
1464   uint32_t i;
1465 
1466   /* Prevent unused argument(s) compilation warning */
1467   UNUSED(hhash);
1468 
1469   /* Restore IMR register content */
1470   WRITE_REG(HASH->IMR, (*(uint32_t *)(mem_ptr)));
1471   mem_ptr += 4U;
1472   /* Restore STR register content */
1473   WRITE_REG(HASH->STR, (*(uint32_t *)(mem_ptr)));
1474   mem_ptr += 4U;
1475   /* Restore CR register content */
1476   WRITE_REG(HASH->CR, (*(uint32_t *)(mem_ptr)));
1477   mem_ptr += 4U;
1478 
1479   /* Reset the HASH processor before restoring the Context
1480   Swap Registers (CSR) */
1481   __HAL_HASH_INIT();
1482 
1483   /* By default, restore all CSR registers */
1484   for (i = HASH_NUMBER_OF_CSR_REGISTERS; i > 0U; i--)
1485   {
1486     WRITE_REG((*(uint32_t *)(csr_ptr)), (*(uint32_t *)(mem_ptr)));
1487     mem_ptr += 4U;
1488     csr_ptr += 4U;
1489   }
1490 }
1491 
1492 
1493 /**
1494   * @brief  Initiate HASH processing suspension when in polling or interruption mode.
1495   * @param  hhash HASH handle.
1496   * @note   Set the handle field SuspendRequest to the appropriate value so that
1497   *         the on-going HASH processing is suspended as soon as the required
1498   *         conditions are met. Note that the actual suspension is carried out
1499   *         by the functions HASH_WriteData() in polling mode and HASH_IT() in
1500   *         interruption mode.
1501   * @retval None
1502   */
1503 void HAL_HASH_SwFeed_ProcessSuspend(HASH_HandleTypeDef *hhash)
1504 {
1505   /* Set Handle Suspend Request field */
1506   hhash->SuspendRequest = HAL_HASH_SUSPEND;
1507 }
1508 
1509 /**
1510   * @brief  Suspend the HASH processing when in DMA mode.
1511   * @param  hhash HASH handle.
1512   * @note   When suspension attempt occurs at the very end of a DMA transfer and
1513   *         all the data have already been entered in the Peripheral, hhash->State is
1514   *         set to HAL_HASH_STATE_READY and the API returns HAL_ERROR. It is
1515   *         recommended to wrap-up the processing in reading the digest as usual.
1516   * @retval HAL status
1517   */
1518 HAL_StatusTypeDef HAL_HASH_DMAFeed_ProcessSuspend(HASH_HandleTypeDef *hhash)
1519 {
1520   uint32_t tmp_remaining_DMATransferSize_inWords;
1521   uint32_t tmp_initial_DMATransferSize_inWords;
1522   uint32_t tmp_words_already_pushed;
1523 
1524   if (hhash->State == HAL_HASH_STATE_READY)
1525   {
1526     return HAL_ERROR;
1527   }
1528   else
1529   {
1530 
1531     /* Make sure there is enough time to suspend the processing */
1532     tmp_remaining_DMATransferSize_inWords = ((DMA_Stream_TypeDef *)hhash->hdmain->Instance)->NDTR;
1533 
1534     if (tmp_remaining_DMATransferSize_inWords <= HASH_DMA_SUSPENSION_WORDS_LIMIT)
1535     {
1536       /* No suspension attempted since almost to the end of the transferred data. */
1537       /* Best option for user code is to wrap up low priority message hashing     */
1538       return HAL_ERROR;
1539     }
1540 
1541     /* Wait for BUSY flag to be reset */
1542     if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK)
1543     {
1544       return HAL_TIMEOUT;
1545     }
1546 
1547     if (__HAL_HASH_GET_FLAG(HASH_FLAG_DCIS) != RESET)
1548     {
1549       return HAL_ERROR;
1550     }
1551 
1552     /* Wait for BUSY flag to be set */
1553     if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, RESET, HASH_TIMEOUTVALUE) != HAL_OK)
1554     {
1555       return HAL_TIMEOUT;
1556     }
1557     /* Disable DMA channel */
1558     /* Note that the Abort function will
1559       - Clear the transfer error flags
1560       - Unlock
1561       - Set the State
1562     */
1563     if (HAL_DMA_Abort(hhash->hdmain) != HAL_OK)
1564     {
1565       return HAL_ERROR;
1566     }
1567 
1568     /* Clear DMAE bit */
1569     CLEAR_BIT(HASH->CR, HASH_CR_DMAE);
1570 
1571     /* Wait for BUSY flag to be reset */
1572     if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK)
1573     {
1574       return HAL_TIMEOUT;
1575     }
1576 
1577     if (__HAL_HASH_GET_FLAG(HASH_FLAG_DCIS) != RESET)
1578     {
1579       return HAL_ERROR;
1580     }
1581 
1582     /* At this point, DMA interface is disabled and no transfer is on-going */
1583     /* Retrieve from the DMA handle how many words remain to be written */
1584     tmp_remaining_DMATransferSize_inWords = ((DMA_Stream_TypeDef *)hhash->hdmain->Instance)->NDTR;
1585 
1586     if (tmp_remaining_DMATransferSize_inWords == 0U)
1587     {
1588       /* All the DMA transfer is actually done. Suspension occurred at the very end
1589          of the transfer. Either the digest computation is about to start (HASH case)
1590          or processing is about to move from one step to another (HMAC case).
1591          In both cases, the processing can't be suspended at this point. It is
1592          safer to
1593          - retrieve the low priority block digest before starting the high
1594            priority block processing (HASH case)
1595          - re-attempt a new suspension (HMAC case)
1596          */
1597       return HAL_ERROR;
1598     }
1599     else
1600     {
1601 
1602       /* Compute how many words were supposed to be transferred by DMA */
1603       tmp_initial_DMATransferSize_inWords = (((hhash->HashInCount % 4U) != 0U) ? \
1604                                              ((hhash->HashInCount + 3U) / 4U) : (hhash->HashInCount / 4U));
1605 
1606       /* If discrepancy between the number of words reported by DMA Peripheral and
1607         the numbers of words entered as reported by HASH Peripheral, correct it */
1608       /* tmp_words_already_pushed reflects the number of words that were already pushed before
1609          the start of DMA transfer (multi-buffer processing case) */
1610       tmp_words_already_pushed = hhash->NbWordsAlreadyPushed;
1611       if (((tmp_words_already_pushed + tmp_initial_DMATransferSize_inWords - \
1612             tmp_remaining_DMATransferSize_inWords) % 16U) != HASH_NBW_PUSHED())
1613       {
1614         tmp_remaining_DMATransferSize_inWords--; /* one less word to be transferred again */
1615       }
1616 
1617       /* Accordingly, update the input pointer that points at the next word to be
1618          transferred to the Peripheral by DMA */
1619       hhash->pHashInBuffPtr +=  4U * (tmp_initial_DMATransferSize_inWords - tmp_remaining_DMATransferSize_inWords) ;
1620 
1621       /* And store in HashInCount the remaining size to transfer (in bytes) */
1622       hhash->HashInCount = 4U * tmp_remaining_DMATransferSize_inWords;
1623 
1624     }
1625 
1626     /* Set State as suspended */
1627     hhash->State = HAL_HASH_STATE_SUSPENDED;
1628 
1629     return HAL_OK;
1630 
1631   }
1632 }
1633 
1634 /**
1635   * @brief  Return the HASH handle error code.
1636   * @param  hhash pointer to a HASH_HandleTypeDef structure.
1637   * @retval HASH Error Code
1638   */
1639 uint32_t HAL_HASH_GetError(HASH_HandleTypeDef *hhash)
1640 {
1641   /* Return HASH Error Code */
1642   return hhash->ErrorCode;
1643 }
1644 /**
1645   * @}
1646   */
1647 
1648 
1649 /**
1650   * @}
1651   */
1652 
1653 /** @defgroup HASH_Private_Functions HASH Private Functions
1654   * @ingroup RTEMSBSPsARMSTM32H7
1655   * @{
1656   */
1657 
1658 /**
1659   * @brief DMA HASH Input Data transfer completion callback.
1660   * @param hdma DMA handle.
1661   * @note  In case of HMAC processing, HASH_DMAXferCplt() initiates
1662   *        the next DMA transfer for the following HMAC step.
1663   * @retval None
1664   */
1665 static void HASH_DMAXferCplt(DMA_HandleTypeDef *hdma)
1666 {
1667   HASH_HandleTypeDef *hhash = (HASH_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
1668   uint32_t inputaddr;
1669   uint32_t buffersize;
1670   HAL_StatusTypeDef status;
1671 
1672   if (hhash->State != HAL_HASH_STATE_SUSPENDED)
1673   {
1674 
1675     /* Disable the DMA transfer */
1676     CLEAR_BIT(HASH->CR, HASH_CR_DMAE);
1677 
1678     if (READ_BIT(HASH->CR, HASH_CR_MODE) == 0U)
1679     {
1680       /* If no HMAC processing, input data transfer is now over */
1681 
1682       /* Change the HASH state to ready */
1683       hhash->State = HAL_HASH_STATE_READY;
1684 
1685       /* Call Input data transfer complete call back */
1686 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
1687       hhash->InCpltCallback(hhash);
1688 #else
1689       HAL_HASH_InCpltCallback(hhash);
1690 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
1691 
1692     }
1693     else
1694     {
1695       /* HMAC processing: depending on the current HMAC step and whether or
1696       not multi-buffer processing is on-going, the next step is initiated
1697       and MDMAT bit is set.  */
1698 
1699 
1700       if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3)
1701       {
1702         /* This is the end of HMAC processing */
1703 
1704         /* Change the HASH state to ready */
1705         hhash->State = HAL_HASH_STATE_READY;
1706 
1707         /* Call Input data transfer complete call back
1708         (note that the last DMA transfer was that of the key
1709         for the outer HASH operation). */
1710 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
1711         hhash->InCpltCallback(hhash);
1712 #else
1713         HAL_HASH_InCpltCallback(hhash);
1714 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
1715 
1716         return;
1717       }
1718       else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1)
1719       {
1720         inputaddr = (uint32_t)hhash->pHashMsgBuffPtr;     /* DMA transfer start address */
1721         buffersize = hhash->HashBuffSize;                 /* DMA transfer size (in bytes) */
1722         hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_2;        /* Move phase from Step 1 to Step 2 */
1723 
1724         /* In case of suspension request, save the new starting parameters */
1725         hhash->HashInCount = hhash->HashBuffSize;         /* Initial DMA transfer size (in bytes) */
1726         hhash->pHashInBuffPtr  = hhash->pHashMsgBuffPtr ; /* DMA transfer start address           */
1727 
1728         hhash->NbWordsAlreadyPushed = 0U;                  /* Reset number of words already pushed */
1729         /* Check whether or not digest calculation must be disabled (in case of multi-buffer HMAC processing) */
1730         if (hhash->DigestCalculationDisable != RESET)
1731         {
1732           /* Digest calculation is disabled: Step 2 must start with MDMAT bit set,
1733           no digest calculation will be triggered at the end of the input buffer feeding to the Peripheral */
1734           __HAL_HASH_SET_MDMAT();
1735         }
1736       }
1737       else  /*case (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)*/
1738       {
1739         if (hhash->DigestCalculationDisable != RESET)
1740         {
1741           /* No automatic move to Step 3 as a new message buffer will be fed to the Peripheral
1742           (case of multi-buffer HMAC processing):
1743           DCAL must not be set.
1744           Phase remains in Step 2, MDMAT remains set at this point.
1745           Change the HASH state to ready and call Input data transfer complete call back. */
1746           hhash->State = HAL_HASH_STATE_READY;
1747 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
1748           hhash->InCpltCallback(hhash);
1749 #else
1750           HAL_HASH_InCpltCallback(hhash);
1751 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
1752           return ;
1753         }
1754         else
1755         {
1756           /* Digest calculation is not disabled (case of single buffer input or last buffer
1757           of multi-buffer HMAC processing) */
1758           inputaddr = (uint32_t)hhash->Init.pKey;       /* DMA transfer start address */
1759           buffersize = hhash->Init.KeySize;             /* DMA transfer size (in bytes) */
1760           hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_3;    /* Move phase from Step 2 to Step 3 */
1761           /* In case of suspension request, save the new starting parameters */
1762           hhash->HashInCount = hhash->Init.KeySize;     /* Initial size for second DMA transfer (input data) */
1763           hhash->pHashInBuffPtr  = hhash->Init.pKey ;   /* address passed to DMA, now entering data message */
1764 
1765           hhash->NbWordsAlreadyPushed = 0U;              /* Reset number of words already pushed */
1766         }
1767       }
1768 
1769       /* Configure the Number of valid bits in last word of the message */
1770       __HAL_HASH_SET_NBVALIDBITS(buffersize);
1771 
1772       /* Set the HASH DMA transfer completion call back */
1773       hhash->hdmain->XferCpltCallback = HASH_DMAXferCplt;
1774 
1775       /* Enable the DMA In DMA stream */
1776       status = HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, \
1777                                 (((buffersize % 4U) != 0U) ? ((buffersize + (4U - (buffersize % 4U))) / 4U) : \
1778                                  (buffersize / 4U)));
1779 
1780       /* Enable DMA requests */
1781       SET_BIT(HASH->CR, HASH_CR_DMAE);
1782 
1783       /* Return function status */
1784       if (status != HAL_OK)
1785       {
1786         /* Update HASH state machine to error */
1787         hhash->State = HAL_HASH_STATE_ERROR;
1788       }
1789       else
1790       {
1791         /* Change HASH state */
1792         hhash->State = HAL_HASH_STATE_BUSY;
1793       }
1794     }
1795   }
1796 
1797   return;
1798 }
1799 
1800 /**
1801   * @brief DMA HASH communication error callback.
1802   * @param hdma DMA handle.
1803   * @note  HASH_DMAError() callback invokes HAL_HASH_ErrorCallback() that
1804   *        can contain user code to manage the error.
1805   * @retval None
1806   */
1807 static void HASH_DMAError(DMA_HandleTypeDef *hdma)
1808 {
1809   HASH_HandleTypeDef *hhash = (HASH_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
1810 
1811   if (hhash->State != HAL_HASH_STATE_SUSPENDED)
1812   {
1813     hhash->ErrorCode |= HAL_HASH_ERROR_DMA;
1814     /* Set HASH state to ready to prevent any blocking issue in user code
1815        present in HAL_HASH_ErrorCallback() */
1816     hhash->State = HAL_HASH_STATE_READY;
1817     /* Set HASH handle status to error */
1818     hhash->Status = HAL_ERROR;
1819 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
1820     hhash->ErrorCallback(hhash);
1821 #else
1822     HAL_HASH_ErrorCallback(hhash);
1823 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
1824     /* After error handling by code user, reset HASH handle HAL status */
1825     hhash->Status = HAL_OK;
1826 
1827   }
1828 }
1829 
1830 /**
1831   * @brief  Feed the input buffer to the HASH Peripheral.
1832   * @param  hhash HASH handle.
1833   * @param  pInBuffer pointer to input buffer.
1834   * @param  Size the size of input buffer in bytes.
1835   * @note   HASH_WriteData() regularly reads hhash->SuspendRequest to check whether
1836   *         or not the HASH processing must be suspended. If this is the case, the
1837   *         processing is suspended when possible and the Peripheral feeding point reached at
1838   *         suspension time is stored in the handle for resumption later on.
1839   * @retval HAL status
1840   */
1841 static HAL_StatusTypeDef HASH_WriteData(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
1842 {
1843   uint32_t buffercounter;
1844   __IO uint32_t inputaddr = (uint32_t) pInBuffer;
1845   uint32_t tmp;
1846 
1847   for (buffercounter = 0U; buffercounter < (Size / 4U); buffercounter++)
1848   {
1849     /* Write input data 4 bytes at a time */
1850     HASH->DIN = *(uint32_t *)inputaddr;
1851     inputaddr += 4U;
1852 
1853     /* If the suspension flag has been raised and if the processing is not about
1854     to end, suspend processing */
1855     if ((hhash->SuspendRequest == HAL_HASH_SUSPEND) && (((buffercounter * 4U) + 4U) < Size))
1856     {
1857       /* wait for flag BUSY not set before  Wait for DINIS = 1*/
1858       if ((buffercounter * 4U) >= 64U)
1859       {
1860         if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK)
1861         {
1862           return HAL_TIMEOUT;
1863         }
1864       }
1865       /* Wait for DINIS = 1, which occurs when 16 32-bit locations are free
1866       in the input buffer */
1867       if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))
1868       {
1869         /* Reset SuspendRequest */
1870         hhash->SuspendRequest = HAL_HASH_SUSPEND_NONE;
1871 
1872         /* Depending whether the key or the input data were fed to the Peripheral, the feeding point
1873         reached at suspension time is not saved in the same handle fields */
1874         if ((hhash->Phase == HAL_HASH_PHASE_PROCESS) || (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2))
1875         {
1876           /* Save current reading and writing locations of Input and Output buffers */
1877           hhash->pHashInBuffPtr = (uint8_t *)inputaddr;
1878           /* Save the number of bytes that remain to be processed at this point */
1879           hhash->HashInCount    =  Size - ((buffercounter * 4U) + 4U);
1880         }
1881         else if ((hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1) || (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3))
1882         {
1883           /* Save current reading and writing locations of Input and Output buffers */
1884           hhash->pHashKeyBuffPtr  = (uint8_t *)inputaddr;
1885           /* Save the number of bytes that remain to be processed at this point */
1886           hhash->HashKeyCount  =  Size - ((buffercounter * 4U) + 4U);
1887         }
1888         else
1889         {
1890           /* Unexpected phase: unlock process and report error */
1891           hhash->State = HAL_HASH_STATE_READY;
1892           __HAL_UNLOCK(hhash);
1893           return HAL_ERROR;
1894         }
1895 
1896         /* Set the HASH state to Suspended and exit to stop entering data */
1897         hhash->State = HAL_HASH_STATE_SUSPENDED;
1898 
1899         return HAL_OK;
1900       } /* if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))  */
1901     } /* if ((hhash->SuspendRequest == HAL_HASH_SUSPEND) && ((buffercounter+4) < Size)) */
1902   }   /* for(buffercounter = 0; buffercounter < Size; buffercounter+=4)                 */
1903 
1904   /* At this point, all the data have been entered to the Peripheral: exit */
1905 
1906   if ((Size % 4U) != 0U)
1907   {
1908     if (hhash->Init.DataType == HASH_DATATYPE_16B)
1909     {
1910       /* Write remaining input data */
1911 
1912       if ((Size % 4U) <= 2U)
1913       {
1914         HASH->DIN = (uint32_t) * (uint16_t *)inputaddr;
1915       }
1916       if ((Size % 4U) == 3U)
1917       {
1918         HASH->DIN = *(uint32_t *)inputaddr;
1919       }
1920 
1921     }
1922     else if ((hhash->Init.DataType == HASH_DATATYPE_8B)
1923              || (hhash->Init.DataType == HASH_DATATYPE_1B))  /* byte swap or bit swap or */
1924     {
1925       /* Write remaining input data */
1926       if ((Size % 4U) == 1U)
1927       {
1928         HASH->DIN = (uint32_t) * (uint8_t *)inputaddr;
1929       }
1930       if ((Size % 4U) == 2U)
1931       {
1932         HASH->DIN = (uint32_t) * (uint16_t *)inputaddr;
1933       }
1934       if ((Size % 4U) == 3U)
1935       {
1936         tmp  = *(uint8_t *)inputaddr;
1937         tmp |= (uint32_t)*(uint8_t *)(inputaddr + 1U) << 8U;
1938         tmp |= (uint32_t)*(uint8_t *)(inputaddr + 2U) << 16U;
1939         HASH->DIN = tmp;
1940       }
1941 
1942     }
1943     else
1944     {
1945       HASH->DIN = *(uint32_t *)inputaddr;
1946     }
1947     /*hhash->HashInCount += 4U;*/
1948   }
1949 
1950 
1951   return  HAL_OK;
1952 }
1953 
1954 /**
1955   * @brief  Retrieve the message digest.
1956   * @param  pMsgDigest pointer to the computed digest.
1957   * @param  Size message digest size in bytes.
1958   * @retval None
1959   */
1960 static void HASH_GetDigest(uint8_t *pMsgDigest, uint8_t Size)
1961 {
1962   uint32_t msgdigest = (uint32_t)pMsgDigest;
1963 
1964   switch (Size)
1965   {
1966     /* Read the message digest */
1967     case 16:  /* MD5 */
1968       *(uint32_t *)(msgdigest) = __REV(HASH->HR[0]);
1969       msgdigest += 4U;
1970       *(uint32_t *)(msgdigest) = __REV(HASH->HR[1]);
1971       msgdigest += 4U;
1972       *(uint32_t *)(msgdigest) = __REV(HASH->HR[2]);
1973       msgdigest += 4U;
1974       *(uint32_t *)(msgdigest) = __REV(HASH->HR[3]);
1975       break;
1976     case 20:  /* SHA1 */
1977       *(uint32_t *)(msgdigest) = __REV(HASH->HR[0]);
1978       msgdigest += 4U;
1979       *(uint32_t *)(msgdigest) = __REV(HASH->HR[1]);
1980       msgdigest += 4U;
1981       *(uint32_t *)(msgdigest) = __REV(HASH->HR[2]);
1982       msgdigest += 4U;
1983       *(uint32_t *)(msgdigest) = __REV(HASH->HR[3]);
1984       msgdigest += 4U;
1985       *(uint32_t *)(msgdigest) = __REV(HASH->HR[4]);
1986       break;
1987     case 28:  /* SHA224 */
1988       *(uint32_t *)(msgdigest) = __REV(HASH->HR[0]);
1989       msgdigest += 4U;
1990       *(uint32_t *)(msgdigest) = __REV(HASH->HR[1]);
1991       msgdigest += 4U;
1992       *(uint32_t *)(msgdigest) = __REV(HASH->HR[2]);
1993       msgdigest += 4U;
1994       *(uint32_t *)(msgdigest) = __REV(HASH->HR[3]);
1995       msgdigest += 4U;
1996       *(uint32_t *)(msgdigest) = __REV(HASH->HR[4]);
1997       msgdigest += 4U;
1998       *(uint32_t *)(msgdigest) = __REV(HASH_DIGEST->HR[5]);
1999       msgdigest += 4U;
2000       *(uint32_t *)(msgdigest) = __REV(HASH_DIGEST->HR[6]);
2001       break;
2002     case 32:   /* SHA256 */
2003       *(uint32_t *)(msgdigest) = __REV(HASH->HR[0]);
2004       msgdigest += 4U;
2005       *(uint32_t *)(msgdigest) = __REV(HASH->HR[1]);
2006       msgdigest += 4U;
2007       *(uint32_t *)(msgdigest) = __REV(HASH->HR[2]);
2008       msgdigest += 4U;
2009       *(uint32_t *)(msgdigest) = __REV(HASH->HR[3]);
2010       msgdigest += 4U;
2011       *(uint32_t *)(msgdigest) = __REV(HASH->HR[4]);
2012       msgdigest += 4U;
2013       *(uint32_t *)(msgdigest) = __REV(HASH_DIGEST->HR[5]);
2014       msgdigest += 4U;
2015       *(uint32_t *)(msgdigest) = __REV(HASH_DIGEST->HR[6]);
2016       msgdigest += 4U;
2017       *(uint32_t *)(msgdigest) = __REV(HASH_DIGEST->HR[7]);
2018       break;
2019     default:
2020       break;
2021   }
2022 }
2023 
2024 
2025 
2026 /**
2027   * @brief  Handle HASH processing Timeout.
2028   * @param  hhash HASH handle.
2029   * @param  Flag specifies the HASH flag to check.
2030   * @param  Status the Flag status (SET or RESET).
2031   * @param  Timeout Timeout duration.
2032   * @retval HAL status
2033   */
2034 static HAL_StatusTypeDef HASH_WaitOnFlagUntilTimeout(HASH_HandleTypeDef *hhash, uint32_t Flag, FlagStatus Status,
2035                                                      uint32_t Timeout)
2036 {
2037   uint32_t tickstart = HAL_GetTick();
2038 
2039   /* Wait until flag is set */
2040   if (Status == RESET)
2041   {
2042     while (__HAL_HASH_GET_FLAG(Flag) == RESET)
2043     {
2044       /* Check for the Timeout */
2045       if (Timeout != HAL_MAX_DELAY)
2046       {
2047         if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
2048         {
2049           /* Set State to Ready to be able to restart later on */
2050           hhash->State  = HAL_HASH_STATE_READY;
2051           /* Store time out issue in handle status */
2052           hhash->Status = HAL_TIMEOUT;
2053 
2054           /* Process Unlocked */
2055           __HAL_UNLOCK(hhash);
2056 
2057           return HAL_TIMEOUT;
2058         }
2059       }
2060     }
2061   }
2062   else
2063   {
2064     while (__HAL_HASH_GET_FLAG(Flag) != RESET)
2065     {
2066       /* Check for the Timeout */
2067       if (Timeout != HAL_MAX_DELAY)
2068       {
2069         if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
2070         {
2071           /* Set State to Ready to be able to restart later on */
2072           hhash->State  = HAL_HASH_STATE_READY;
2073           /* Store time out issue in handle status */
2074           hhash->Status = HAL_TIMEOUT;
2075 
2076           /* Process Unlocked */
2077           __HAL_UNLOCK(hhash);
2078 
2079           return HAL_TIMEOUT;
2080         }
2081       }
2082     }
2083   }
2084   return HAL_OK;
2085 }
2086 
2087 
2088 /**
2089   * @brief  HASH processing in interruption mode.
2090   * @param  hhash HASH handle.
2091   * @note   HASH_IT() regularly reads hhash->SuspendRequest to check whether
2092   *         or not the HASH processing must be suspended. If this is the case, the
2093   *         processing is suspended when possible and the Peripheral feeding point reached at
2094   *         suspension time is stored in the handle for resumption later on.
2095   * @retval HAL status
2096   */
2097 static HAL_StatusTypeDef HASH_IT(HASH_HandleTypeDef *hhash)
2098 {
2099   if (hhash->State == HAL_HASH_STATE_BUSY)
2100   {
2101     /* ITCounter must not be equal to 0 at this point. Report an error if this is the case. */
2102     if (hhash->HashITCounter == 0U)
2103     {
2104       /* Disable Interrupts */
2105       __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
2106       /* HASH state set back to Ready to prevent any issue in user code
2107          present in HAL_HASH_ErrorCallback() */
2108       hhash->State = HAL_HASH_STATE_READY;
2109       return HAL_ERROR;
2110     }
2111     else if (hhash->HashITCounter == 1U)
2112     {
2113       /* This is the first call to HASH_IT, the first input data are about to be
2114          entered in the Peripheral. A specific processing is carried out at this point to
2115          start-up the processing. */
2116       hhash->HashITCounter = 2U;
2117     }
2118     else
2119     {
2120       /* Cruise speed reached, HashITCounter remains equal to 3 until the end of
2121         the HASH processing or the end of the current step for HMAC processing. */
2122       hhash->HashITCounter = 3U;
2123     }
2124 
2125     /* If digest is ready */
2126     if (__HAL_HASH_GET_FLAG(HASH_FLAG_DCIS))
2127     {
2128       /* Read the digest */
2129       HASH_GetDigest(hhash->pHashOutBuffPtr, HASH_DIGEST_LENGTH());
2130 
2131       /* Disable Interrupts */
2132       __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
2133       /* Change the HASH state */
2134       hhash->State = HAL_HASH_STATE_READY;
2135       /* Reset HASH state machine */
2136       hhash->Phase = HAL_HASH_PHASE_READY;
2137       /* Call digest computation complete call back */
2138 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
2139       hhash->DgstCpltCallback(hhash);
2140 #else
2141       HAL_HASH_DgstCpltCallback(hhash);
2142 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
2143 
2144       return HAL_OK;
2145     }
2146 
2147     /* If Peripheral ready to accept new data */
2148     if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))
2149     {
2150 
2151       /* If the suspension flag has been raised and if the processing is not about
2152          to end, suspend processing */
2153       if ((hhash->HashInCount != 0U) && (hhash->SuspendRequest == HAL_HASH_SUSPEND))
2154       {
2155         /* Disable Interrupts */
2156         __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
2157 
2158         /* Reset SuspendRequest */
2159         hhash->SuspendRequest = HAL_HASH_SUSPEND_NONE;
2160 
2161         /* Change the HASH state */
2162         hhash->State = HAL_HASH_STATE_SUSPENDED;
2163 
2164         return HAL_OK;
2165       }
2166 
2167       /* Enter input data in the Peripheral through HASH_Write_Block_Data() call and
2168         check whether the digest calculation has been triggered */
2169       if (HASH_Write_Block_Data(hhash) == HASH_DIGEST_CALCULATION_STARTED)
2170       {
2171         /* Call Input data transfer complete call back
2172            (called at the end of each step for HMAC) */
2173 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
2174         hhash->InCpltCallback(hhash);
2175 #else
2176         HAL_HASH_InCpltCallback(hhash);
2177 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
2178 
2179         if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1)
2180         {
2181           /* Wait until Peripheral is not busy anymore */
2182           if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK)
2183           {
2184             /* Disable Interrupts */
2185             __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
2186             return HAL_TIMEOUT;
2187           }
2188           /* Initialization start for HMAC STEP 2 */
2189           hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_2;        /* Move phase from Step 1 to Step 2 */
2190           __HAL_HASH_SET_NBVALIDBITS(hhash->HashBuffSize);  /* Set NBLW for the input message */
2191           hhash->HashInCount = hhash->HashBuffSize;         /* Set the input data size (in bytes) */
2192           hhash->pHashInBuffPtr = hhash->pHashMsgBuffPtr;   /* Set the input data address */
2193           hhash->HashITCounter = 1;                         /* Set ITCounter to 1 to indicate the start
2194                                                                of a new phase */
2195           __HAL_HASH_ENABLE_IT(HASH_IT_DINI);               /* Enable IT (was disabled in HASH_Write_Block_Data) */
2196         }
2197         else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)
2198         {
2199           /* Wait until Peripheral is not busy anymore */
2200           if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK)
2201           {
2202             /* Disable Interrupts */
2203             __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
2204             return HAL_TIMEOUT;
2205           }
2206           /* Initialization start for HMAC STEP 3 */
2207           hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_3;         /* Move phase from Step 2 to Step 3 */
2208           __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);   /* Set NBLW for the key */
2209           hhash->HashInCount = hhash->Init.KeySize;          /* Set the key size (in bytes) */
2210           hhash->pHashInBuffPtr = hhash->Init.pKey;          /* Set the key address */
2211           hhash->HashITCounter = 1;                          /* Set ITCounter to 1 to indicate the start
2212                                                                 of a new phase */
2213           __HAL_HASH_ENABLE_IT(HASH_IT_DINI);                /* Enable IT (was disabled in HASH_Write_Block_Data) */
2214         }
2215         else
2216         {
2217           /* Nothing to do */
2218         }
2219       } /* if (HASH_Write_Block_Data(hhash) == HASH_DIGEST_CALCULATION_STARTED) */
2220     }  /* if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))*/
2221 
2222     /* Return function status */
2223     return HAL_OK;
2224   }
2225   else
2226   {
2227     return HAL_BUSY;
2228   }
2229 }
2230 
2231 
2232 /**
2233   * @brief  Write a block of data in HASH Peripheral in interruption mode.
2234   * @param  hhash HASH handle.
2235   * @note   HASH_Write_Block_Data() is called under interruption by HASH_IT().
2236   * @retval HAL status
2237   */
2238 static uint32_t HASH_Write_Block_Data(HASH_HandleTypeDef *hhash)
2239 {
2240   uint32_t inputaddr;
2241   uint32_t buffercounter;
2242   uint32_t inputcounter;
2243   uint32_t ret = HASH_DIGEST_CALCULATION_NOT_STARTED;
2244 
2245   /* If there are more than 64 bytes remaining to be entered */
2246   if (hhash->HashInCount > 64U)
2247   {
2248     inputaddr = (uint32_t)hhash->pHashInBuffPtr;
2249     /* Write the Input block in the Data IN register
2250       (16 32-bit words, or 64 bytes are entered) */
2251     for (buffercounter = 0U; buffercounter < 64U; buffercounter += 4U)
2252     {
2253       HASH->DIN = *(uint32_t *)inputaddr;
2254       inputaddr += 4U;
2255     }
2256     /* If this is the start of input data entering, an additional word
2257       must be entered to start up the HASH processing */
2258     if (hhash->HashITCounter == 2U)
2259     {
2260       HASH->DIN = *(uint32_t *)inputaddr;
2261       if (hhash->HashInCount >= 68U)
2262       {
2263         /* There are still data waiting to be entered in the Peripheral.
2264            Decrement buffer counter and set pointer to the proper
2265            memory location for the next data entering round. */
2266         hhash->HashInCount -= 68U;
2267         hhash->pHashInBuffPtr += 68U;
2268       }
2269       else
2270       {
2271         /* All the input buffer has been fed to the HW. */
2272         hhash->HashInCount = 0U;
2273       }
2274     }
2275     else
2276     {
2277       /* 64 bytes have been entered and there are still some remaining:
2278          Decrement buffer counter and set pointer to the proper
2279         memory location for the next data entering round.*/
2280       hhash->HashInCount -= 64U;
2281       hhash->pHashInBuffPtr += 64U;
2282     }
2283   }
2284   else
2285   {
2286     /* 64 or less bytes remain to be entered. This is the last
2287       data entering round. */
2288 
2289     /* Get the buffer address */
2290     inputaddr = (uint32_t)hhash->pHashInBuffPtr;
2291     /* Get the buffer counter */
2292     inputcounter = hhash->HashInCount;
2293     /* Disable Interrupts */
2294     __HAL_HASH_DISABLE_IT(HASH_IT_DINI);
2295 
2296     /* Write the Input block in the Data IN register */
2297     for (buffercounter = 0U; buffercounter < ((inputcounter + 3U) / 4U); buffercounter++)
2298     {
2299       HASH->DIN = *(uint32_t *)inputaddr;
2300       inputaddr += 4U;
2301     }
2302 
2303     if (hhash->Accumulation == 1U)
2304     {
2305       /* Field accumulation is set, API only feeds data to the Peripheral and under interruption.
2306          The digest computation will be started when the last buffer data are entered. */
2307 
2308       /* Reset multi buffers accumulation flag */
2309       hhash->Accumulation = 0U;
2310       /* Change the HASH state */
2311       hhash->State = HAL_HASH_STATE_READY;
2312       /* Call Input data transfer complete call back */
2313 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
2314       hhash->InCpltCallback(hhash);
2315 #else
2316       HAL_HASH_InCpltCallback(hhash);
2317 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
2318     }
2319     else
2320     {
2321       /* Start the Digest calculation */
2322       __HAL_HASH_START_DIGEST();
2323       /* Return indication that digest calculation has started:
2324          this return value triggers the call to Input data transfer
2325          complete call back as well as the proper transition from
2326          one step to another in HMAC mode. */
2327       ret = HASH_DIGEST_CALCULATION_STARTED;
2328     }
2329     /* Reset buffer counter */
2330     hhash->HashInCount = 0;
2331   }
2332 
2333   /* Return whether or digest calculation has started */
2334   return ret;
2335 }
2336 
2337 /**
2338   * @brief  HMAC processing in polling mode.
2339   * @param  hhash HASH handle.
2340   * @param  Timeout Timeout value.
2341   * @retval HAL status
2342   */
2343 static HAL_StatusTypeDef HMAC_Processing(HASH_HandleTypeDef *hhash, uint32_t Timeout)
2344 {
2345   /* Ensure first that Phase is correct */
2346   if ((hhash->Phase != HAL_HASH_PHASE_HMAC_STEP_1) && (hhash->Phase != HAL_HASH_PHASE_HMAC_STEP_2)
2347       && (hhash->Phase != HAL_HASH_PHASE_HMAC_STEP_3))
2348   {
2349     /* Change the HASH state */
2350     hhash->State = HAL_HASH_STATE_READY;
2351 
2352     /* Process Unlock */
2353     __HAL_UNLOCK(hhash);
2354 
2355     /* Return function status */
2356     return HAL_ERROR;
2357   }
2358 
2359   /* HMAC Step 1 processing */
2360   if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1)
2361   {
2362     /************************** STEP 1 ******************************************/
2363     /* Configure the Number of valid bits in last word of the message */
2364     __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
2365 
2366     /* Write input buffer in Data register */
2367     hhash->Status = HASH_WriteData(hhash, hhash->pHashKeyBuffPtr, hhash->HashKeyCount);
2368     if (hhash->Status != HAL_OK)
2369     {
2370       return hhash->Status;
2371     }
2372 
2373     /* Check whether or not key entering process has been suspended */
2374     if (hhash->State == HAL_HASH_STATE_SUSPENDED)
2375     {
2376       /* Process Unlocked */
2377       __HAL_UNLOCK(hhash);
2378 
2379       /* Stop right there and return function status */
2380       return HAL_OK;
2381     }
2382 
2383     /* No processing suspension at this point: set DCAL bit. */
2384     __HAL_HASH_START_DIGEST();
2385 
2386     /* Wait for BUSY flag to be cleared */
2387     if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, Timeout) != HAL_OK)
2388     {
2389       return HAL_TIMEOUT;
2390     }
2391 
2392     /* Move from Step 1 to Step 2 */
2393     hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_2;
2394 
2395   }
2396 
2397   /* HMAC Step 2 processing.
2398      After phase check, HMAC_Processing() may
2399      - directly start up from this point in resumption case
2400        if the same Step 2 processing was suspended previously
2401     - or fall through from the Step 1 processing carried out hereabove */
2402   if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)
2403   {
2404     /************************** STEP 2 ******************************************/
2405     /* Configure the Number of valid bits in last word of the message */
2406     __HAL_HASH_SET_NBVALIDBITS(hhash->HashBuffSize);
2407 
2408     /* Write input buffer in Data register */
2409     hhash->Status = HASH_WriteData(hhash, hhash->pHashInBuffPtr, hhash->HashInCount);
2410     if (hhash->Status != HAL_OK)
2411     {
2412       return hhash->Status;
2413     }
2414 
2415     /* Check whether or not data entering process has been suspended */
2416     if (hhash->State == HAL_HASH_STATE_SUSPENDED)
2417     {
2418       /* Process Unlocked */
2419       __HAL_UNLOCK(hhash);
2420 
2421       /* Stop right there and return function status */
2422       return HAL_OK;
2423     }
2424 
2425     /* No processing suspension at this point: set DCAL bit. */
2426     __HAL_HASH_START_DIGEST();
2427 
2428     /* Wait for BUSY flag to be cleared */
2429     if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, Timeout) != HAL_OK)
2430     {
2431       return HAL_TIMEOUT;
2432     }
2433 
2434     /* Move from Step 2 to Step 3 */
2435     hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_3;
2436     /* In case Step 1 phase was suspended then resumed,
2437        set again Key input buffers and size before moving to
2438        next step */
2439     hhash->pHashKeyBuffPtr = hhash->Init.pKey;
2440     hhash->HashKeyCount    = hhash->Init.KeySize;
2441   }
2442 
2443 
2444   /* HMAC Step 3 processing.
2445       After phase check, HMAC_Processing() may
2446       - directly start up from this point in resumption case
2447         if the same Step 3 processing was suspended previously
2448      - or fall through from the Step 2 processing carried out hereabove */
2449   if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3)
2450   {
2451     /************************** STEP 3 ******************************************/
2452     /* Configure the Number of valid bits in last word of the message */
2453     __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
2454 
2455     /* Write input buffer in Data register */
2456     hhash->Status = HASH_WriteData(hhash, hhash->pHashKeyBuffPtr, hhash->HashKeyCount);
2457     if (hhash->Status != HAL_OK)
2458     {
2459       return hhash->Status;
2460     }
2461 
2462     /* Check whether or not key entering process has been suspended */
2463     if (hhash->State == HAL_HASH_STATE_SUSPENDED)
2464     {
2465       /* Process Unlocked */
2466       __HAL_UNLOCK(hhash);
2467 
2468       /* Stop right there and return function status */
2469       return HAL_OK;
2470     }
2471 
2472     /* No processing suspension at this point: start the Digest calculation. */
2473     __HAL_HASH_START_DIGEST();
2474 
2475     /* Wait for DCIS flag to be set */
2476     if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_DCIS, RESET, Timeout) != HAL_OK)
2477     {
2478       return HAL_TIMEOUT;
2479     }
2480 
2481     /* Read the message digest */
2482     HASH_GetDigest(hhash->pHashOutBuffPtr, HASH_DIGEST_LENGTH());
2483 
2484     /* Reset HASH state machine */
2485     hhash->Phase = HAL_HASH_PHASE_READY;
2486   }
2487 
2488   /* Change the HASH state */
2489   hhash->State = HAL_HASH_STATE_READY;
2490 
2491   /* Process Unlock */
2492   __HAL_UNLOCK(hhash);
2493 
2494   /* Return function status */
2495   return HAL_OK;
2496 }
2497 
2498 
2499 /**
2500   * @brief  Initialize the HASH peripheral, next process pInBuffer then
2501   *         read the computed digest.
2502   * @note   Digest is available in pOutBuffer.
2503   * @param  hhash HASH handle.
2504   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
2505   * @param  Size length of the input buffer in bytes.
2506   * @param  pOutBuffer pointer to the computed digest.
2507   * @param  Timeout Timeout value.
2508   * @param  Algorithm HASH algorithm.
2509   * @retval HAL status
2510   */
2511 HAL_StatusTypeDef HASH_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer,
2512                              uint32_t Timeout, uint32_t Algorithm)
2513 {
2514   uint8_t *pInBuffer_tmp;  /* input data address, input parameter of HASH_WriteData()         */
2515   uint32_t Size_tmp; /* input data size (in bytes), input parameter of HASH_WriteData() */
2516   HAL_HASH_StateTypeDef State_tmp = hhash->State;
2517 
2518 
2519   /* Initiate HASH processing in case of start or resumption */
2520   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
2521   {
2522     /* Check input parameters */
2523     if ((pInBuffer == NULL) || (pOutBuffer == NULL))
2524     {
2525       hhash->State = HAL_HASH_STATE_READY;
2526       return  HAL_ERROR;
2527     }
2528 
2529     /* Process Locked */
2530     __HAL_LOCK(hhash);
2531 
2532     /* Check if initialization phase has not been already performed */
2533     if (hhash->Phase == HAL_HASH_PHASE_READY)
2534     {
2535       /* Change the HASH state */
2536       hhash->State = HAL_HASH_STATE_BUSY;
2537 
2538       /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
2539       MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT);
2540 
2541       /* Configure the number of valid bits in last word of the message */
2542       __HAL_HASH_SET_NBVALIDBITS(Size);
2543 
2544       /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as
2545       input parameters of HASH_WriteData() */
2546       pInBuffer_tmp = pInBuffer;   /* pInBuffer_tmp is set to the input data address */
2547       Size_tmp = Size;             /* Size_tmp contains the input data size in bytes */
2548 
2549       /* Set the phase */
2550       hhash->Phase = HAL_HASH_PHASE_PROCESS;
2551     }
2552     else if (hhash->Phase == HAL_HASH_PHASE_PROCESS)
2553     {
2554       /* if the Peripheral has already been initialized, two cases are possible */
2555 
2556       /* Process resumption time ... */
2557       if (hhash->State == HAL_HASH_STATE_SUSPENDED)
2558       {
2559         /* Since this is resumption, pInBuffer_tmp and Size_tmp are not set
2560         to the API input parameters but to those saved beforehand by HASH_WriteData()
2561         when the processing was suspended */
2562         pInBuffer_tmp = hhash->pHashInBuffPtr;
2563         Size_tmp = hhash->HashInCount;
2564       }
2565       /* ... or multi-buffer HASH processing end */
2566       else
2567       {
2568         /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as
2569         input parameters of HASH_WriteData() */
2570         pInBuffer_tmp = pInBuffer;
2571         Size_tmp = Size;
2572         /* Configure the number of valid bits in last word of the message */
2573         __HAL_HASH_SET_NBVALIDBITS(Size);
2574       }
2575       /* Change the HASH state */
2576       hhash->State = HAL_HASH_STATE_BUSY;
2577     }
2578     else
2579     {
2580       /* Phase error */
2581       hhash->State = HAL_HASH_STATE_READY;
2582 
2583       /* Process Unlocked */
2584       __HAL_UNLOCK(hhash);
2585 
2586       /* Return function status */
2587       return HAL_ERROR;
2588     }
2589 
2590 
2591     /* Write input buffer in Data register */
2592     hhash->Status = HASH_WriteData(hhash, pInBuffer_tmp, Size_tmp);
2593     if (hhash->Status != HAL_OK)
2594     {
2595       return hhash->Status;
2596     }
2597 
2598     /* If the process has not been suspended, carry on to digest calculation */
2599     if (hhash->State != HAL_HASH_STATE_SUSPENDED)
2600     {
2601       /* Start the Digest calculation */
2602       __HAL_HASH_START_DIGEST();
2603 
2604       /* Wait for DCIS flag to be set */
2605       if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_DCIS, RESET, Timeout) != HAL_OK)
2606       {
2607         return HAL_TIMEOUT;
2608       }
2609 
2610       /* Read the message digest */
2611       HASH_GetDigest(pOutBuffer, HASH_DIGEST_LENGTH());
2612 
2613       /* Change the HASH state */
2614       hhash->State = HAL_HASH_STATE_READY;
2615 
2616       /* Reset HASH state machine */
2617       hhash->Phase = HAL_HASH_PHASE_READY;
2618 
2619     }
2620 
2621     /* Process Unlocked */
2622     __HAL_UNLOCK(hhash);
2623 
2624     /* Return function status */
2625     return HAL_OK;
2626 
2627   }
2628   else
2629   {
2630     return HAL_BUSY;
2631   }
2632 }
2633 
2634 
2635 /**
2636   * @brief  If not already done, initialize the HASH peripheral then
2637   *         processes pInBuffer.
2638   * @note   Field hhash->Phase of HASH handle is tested to check whether or not
2639   *         the Peripheral has already been initialized.
2640   * @note   The input buffer size (in bytes) must be a multiple of 4 otherwise, the
2641   *         HASH digest computation is corrupted.
2642   * @param  hhash HASH handle.
2643   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
2644   * @param  Size length of the input buffer in bytes, must be a multiple of 4.
2645   * @param  Algorithm HASH algorithm.
2646   * @retval HAL status
2647   */
2648 HAL_StatusTypeDef HASH_Accumulate(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm)
2649 {
2650   uint8_t *pInBuffer_tmp;   /* input data address, input parameter of HASH_WriteData()         */
2651   uint32_t Size_tmp;  /* input data size (in bytes), input parameter of HASH_WriteData() */
2652   HAL_HASH_StateTypeDef State_tmp = hhash->State;
2653 
2654   /* Make sure the input buffer size (in bytes) is a multiple of 4 */
2655   if ((Size % 4U) != 0U)
2656   {
2657     return  HAL_ERROR;
2658   }
2659 
2660   /* Initiate HASH processing in case of start or resumption */
2661   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
2662   {
2663     /* Check input parameters */
2664     if ((pInBuffer == NULL) || (Size == 0U))
2665     {
2666       hhash->State = HAL_HASH_STATE_READY;
2667       return  HAL_ERROR;
2668     }
2669 
2670     /* Process Locked */
2671     __HAL_LOCK(hhash);
2672 
2673     /* If resuming the HASH processing */
2674     if (hhash->State == HAL_HASH_STATE_SUSPENDED)
2675     {
2676       /* Change the HASH state */
2677       hhash->State = HAL_HASH_STATE_BUSY;
2678 
2679       /* Since this is resumption, pInBuffer_tmp and Size_tmp are not set
2680          to the API input parameters but to those saved beforehand by HASH_WriteData()
2681          when the processing was suspended */
2682       pInBuffer_tmp = hhash->pHashInBuffPtr;  /* pInBuffer_tmp is set to the input data address */
2683       Size_tmp = hhash->HashInCount;          /* Size_tmp contains the input data size in bytes */
2684 
2685     }
2686     else
2687     {
2688       /* Change the HASH state */
2689       hhash->State = HAL_HASH_STATE_BUSY;
2690 
2691       /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as
2692          input parameters of HASH_WriteData() */
2693       pInBuffer_tmp = pInBuffer;    /* pInBuffer_tmp is set to the input data address */
2694       Size_tmp = Size;              /* Size_tmp contains the input data size in bytes */
2695 
2696       /* Check if initialization phase has already be performed */
2697       if (hhash->Phase == HAL_HASH_PHASE_READY)
2698       {
2699         /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
2700         MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT);
2701       }
2702 
2703       /* Set the phase */
2704       hhash->Phase = HAL_HASH_PHASE_PROCESS;
2705 
2706     }
2707 
2708     /* Write input buffer in Data register */
2709     hhash->Status = HASH_WriteData(hhash, pInBuffer_tmp, Size_tmp);
2710     if (hhash->Status != HAL_OK)
2711     {
2712       return hhash->Status;
2713     }
2714 
2715     /* If the process has not been suspended, move the state to Ready */
2716     if (hhash->State != HAL_HASH_STATE_SUSPENDED)
2717     {
2718       /* Change the HASH state */
2719       hhash->State = HAL_HASH_STATE_READY;
2720     }
2721 
2722     /* Process Unlocked */
2723     __HAL_UNLOCK(hhash);
2724 
2725     /* Return function status */
2726     return HAL_OK;
2727 
2728   }
2729   else
2730   {
2731     return HAL_BUSY;
2732   }
2733 
2734 
2735 }
2736 
2737 
2738 /**
2739   * @brief  If not already done, initialize the HASH peripheral then
2740   *         processes pInBuffer in interruption mode.
2741   * @note   Field hhash->Phase of HASH handle is tested to check whether or not
2742   *         the Peripheral has already been initialized.
2743   * @note   The input buffer size (in bytes) must be a multiple of 4 otherwise, the
2744   *         HASH digest computation is corrupted.
2745   * @param  hhash HASH handle.
2746   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
2747   * @param  Size length of the input buffer in bytes, must be a multiple of 4.
2748   * @param  Algorithm HASH algorithm.
2749   * @retval HAL status
2750   */
2751 HAL_StatusTypeDef HASH_Accumulate_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm)
2752 {
2753   HAL_HASH_StateTypeDef State_tmp = hhash->State;
2754   __IO uint32_t inputaddr = (uint32_t) pInBuffer;
2755   uint32_t SizeVar = Size;
2756 
2757   /* Make sure the input buffer size (in bytes) is a multiple of 4 */
2758   if ((Size % 4U) != 0U)
2759   {
2760     return  HAL_ERROR;
2761   }
2762 
2763   /* Initiate HASH processing in case of start or resumption */
2764   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
2765   {
2766     /* Check input parameters */
2767     if ((pInBuffer == NULL) || (Size == 0U))
2768     {
2769       hhash->State = HAL_HASH_STATE_READY;
2770       return  HAL_ERROR;
2771     }
2772 
2773     /* Process Locked */
2774     __HAL_LOCK(hhash);
2775 
2776     /* If resuming the HASH processing */
2777     if (hhash->State == HAL_HASH_STATE_SUSPENDED)
2778     {
2779       /* Change the HASH state */
2780       hhash->State = HAL_HASH_STATE_BUSY;
2781     }
2782     else
2783     {
2784       /* Change the HASH state */
2785       hhash->State = HAL_HASH_STATE_BUSY;
2786 
2787       /* Check if initialization phase has already be performed */
2788       if (hhash->Phase == HAL_HASH_PHASE_READY)
2789       {
2790         /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
2791         MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT);
2792         hhash->HashITCounter = 1;
2793       }
2794       else
2795       {
2796         hhash->HashITCounter = 3; /* 'cruise-speed' reached during a previous buffer processing */
2797       }
2798 
2799       /* Set the phase */
2800       hhash->Phase = HAL_HASH_PHASE_PROCESS;
2801 
2802       /* If DINIS is equal to 0 (for example if an incomplete block has been previously
2803        fed to the Peripheral), the DINIE interruption won't be triggered when DINIE is set.
2804        Therefore, first words are manually entered until DINIS raises, or until there
2805        is not more data to enter. */
2806       while ((!(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))) && (SizeVar > 0U))
2807       {
2808 
2809         /* Write input data 4 bytes at a time */
2810         HASH->DIN = *(uint32_t *)inputaddr;
2811         inputaddr += 4U;
2812         SizeVar -= 4U;
2813       }
2814 
2815       /* If DINIS is still not set or if all the data have been fed, stop here */
2816       if ((!(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))) || (SizeVar == 0U))
2817       {
2818         /* Change the HASH state */
2819         hhash->State = HAL_HASH_STATE_READY;
2820 
2821         /* Process Unlock */
2822         __HAL_UNLOCK(hhash);
2823 
2824         /* Return function status */
2825         return HAL_OK;
2826       }
2827 
2828       /* otherwise, carry on in interrupt-mode */
2829       hhash->HashInCount = SizeVar;               /* Counter used to keep track of number of data
2830                                                   to be fed to the Peripheral */
2831       hhash->pHashInBuffPtr = (uint8_t *)inputaddr;       /* Points at data which will be fed to the Peripheral at
2832                                                   the next interruption */
2833       /* In case of suspension, hhash->HashInCount and hhash->pHashInBuffPtr contain
2834          the information describing where the HASH process is stopped.
2835          These variables are used later on to resume the HASH processing at the
2836          correct location. */
2837 
2838     }
2839 
2840     /* Set multi buffers accumulation flag */
2841     hhash->Accumulation = 1U;
2842 
2843     /* Process Unlock */
2844     __HAL_UNLOCK(hhash);
2845 
2846     /* Enable Data Input interrupt */
2847     __HAL_HASH_ENABLE_IT(HASH_IT_DINI);
2848 
2849     /* Return function status */
2850     return HAL_OK;
2851 
2852   }
2853   else
2854   {
2855     return HAL_BUSY;
2856   }
2857 
2858 }
2859 
2860 
2861 
2862 /**
2863   * @brief  Initialize the HASH peripheral, next process pInBuffer then
2864   *         read the computed digest in interruption mode.
2865   * @note   Digest is available in pOutBuffer.
2866   * @param  hhash HASH handle.
2867   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
2868   * @param  Size length of the input buffer in bytes.
2869   * @param  pOutBuffer pointer to the computed digest.
2870   * @param  Algorithm HASH algorithm.
2871   * @retval HAL status
2872   */
2873 HAL_StatusTypeDef HASH_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer,
2874                                 uint32_t Algorithm)
2875 {
2876   HAL_HASH_StateTypeDef State_tmp = hhash->State;
2877   __IO uint32_t inputaddr = (uint32_t) pInBuffer;
2878   uint32_t polling_step = 0U;
2879   uint32_t initialization_skipped = 0U;
2880   uint32_t SizeVar = Size;
2881 
2882   /* If State is ready or suspended, start or resume IT-based HASH processing */
2883   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
2884   {
2885     /* Check input parameters */
2886     if ((pInBuffer == NULL) || (Size == 0U) || (pOutBuffer == NULL))
2887     {
2888       hhash->State = HAL_HASH_STATE_READY;
2889       return  HAL_ERROR;
2890     }
2891 
2892     /* Process Locked */
2893     __HAL_LOCK(hhash);
2894 
2895     /* Change the HASH state */
2896     hhash->State = HAL_HASH_STATE_BUSY;
2897 
2898     /* Initialize IT counter */
2899     hhash->HashITCounter = 1;
2900 
2901     /* Check if initialization phase has already be performed */
2902     if (hhash->Phase == HAL_HASH_PHASE_READY)
2903     {
2904       /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
2905       MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT);
2906 
2907       /* Configure the number of valid bits in last word of the message */
2908       __HAL_HASH_SET_NBVALIDBITS(SizeVar);
2909 
2910 
2911       hhash->HashInCount = SizeVar;            /* Counter used to keep track of number of data
2912                                                   to be fed to the Peripheral */
2913       hhash->pHashInBuffPtr = pInBuffer;       /* Points at data which will be fed to the Peripheral at
2914                                                   the next interruption */
2915       /* In case of suspension, hhash->HashInCount and hhash->pHashInBuffPtr contain
2916          the information describing where the HASH process is stopped.
2917          These variables are used later on to resume the HASH processing at the
2918          correct location. */
2919 
2920       hhash->pHashOutBuffPtr = pOutBuffer;     /* Points at the computed digest */
2921     }
2922     else
2923     {
2924       initialization_skipped = 1; /* info user later on in case of multi-buffer */
2925     }
2926 
2927     /* Set the phase */
2928     hhash->Phase = HAL_HASH_PHASE_PROCESS;
2929 
2930     /* If DINIS is equal to 0 (for example if an incomplete block has been previously
2931       fed to the Peripheral), the DINIE interruption won't be triggered when DINIE is set.
2932       Therefore, first words are manually entered until DINIS raises. */
2933     while ((!(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))) && (SizeVar > 3U))
2934     {
2935       polling_step = 1U; /* note that some words are entered before enabling the interrupt */
2936 
2937       /* Write input data 4 bytes at a time */
2938       HASH->DIN = *(uint32_t *)inputaddr;
2939       inputaddr += 4U;
2940       SizeVar -= 4U;
2941     }
2942 
2943     if (polling_step == 1U)
2944     {
2945       if (SizeVar == 0U)
2946       {
2947         /* If all the data have been entered at this point, it only remains to
2948          read the digest */
2949         hhash->pHashOutBuffPtr = pOutBuffer;     /* Points at the computed digest */
2950 
2951         /* Start the Digest calculation */
2952         __HAL_HASH_START_DIGEST();
2953         /* Process Unlock */
2954         __HAL_UNLOCK(hhash);
2955 
2956         /* Enable Interrupts */
2957         __HAL_HASH_ENABLE_IT(HASH_IT_DCI);
2958 
2959         /* Return function status */
2960         return HAL_OK;
2961       }
2962       else if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))
2963       {
2964         /* It remains data to enter and the Peripheral is ready to trigger DINIE,
2965            carry on as usual.
2966            Update HashInCount and pHashInBuffPtr accordingly. */
2967         hhash->HashInCount = SizeVar;
2968         hhash->pHashInBuffPtr = (uint8_t *)inputaddr;
2969         /* Update the configuration of the number of valid bits in last word of the message */
2970         __HAL_HASH_SET_NBVALIDBITS(SizeVar);
2971         hhash->pHashOutBuffPtr = pOutBuffer;  /* Points at the computed digest */
2972         if (initialization_skipped == 1U)
2973         {
2974           hhash->HashITCounter = 3; /* 'cruise-speed' reached during a previous buffer processing */
2975         }
2976       }
2977       else
2978       {
2979         /* DINIS is not set but it remains a few data to enter (not enough for a full word).
2980            Manually enter the last bytes before enabling DCIE. */
2981         __HAL_HASH_SET_NBVALIDBITS(SizeVar);
2982         HASH->DIN = *(uint32_t *)inputaddr;
2983 
2984         /* Start the Digest calculation */
2985         hhash->pHashOutBuffPtr = pOutBuffer;     /* Points at the computed digest */
2986         __HAL_HASH_START_DIGEST();
2987         /* Process Unlock */
2988         __HAL_UNLOCK(hhash);
2989 
2990         /* Enable Interrupts */
2991         __HAL_HASH_ENABLE_IT(HASH_IT_DCI);
2992 
2993         /* Return function status */
2994         return HAL_OK;
2995       }
2996     } /*  if (polling_step == 1) */
2997 
2998 
2999     /* Process Unlock */
3000     __HAL_UNLOCK(hhash);
3001 
3002     /* Enable Interrupts */
3003     __HAL_HASH_ENABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
3004 
3005     /* Return function status */
3006     return HAL_OK;
3007   }
3008   else
3009   {
3010     return HAL_BUSY;
3011   }
3012 
3013 }
3014 
3015 
3016 /**
3017   * @brief  Initialize the HASH peripheral then initiate a DMA transfer
3018   *         to feed the input buffer to the Peripheral.
3019   * @note   If MDMAT bit is set before calling this function (multi-buffer
3020   *          HASH processing case), the input buffer size (in bytes) must be
3021   *          a multiple of 4 otherwise, the HASH digest computation is corrupted.
3022   *          For the processing of the last buffer of the thread, MDMAT bit must
3023   *          be reset and the buffer length (in bytes) doesn't have to be a
3024   *          multiple of 4.
3025   * @param  hhash HASH handle.
3026   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
3027   * @param  Size length of the input buffer in bytes.
3028   * @param  Algorithm HASH algorithm.
3029   * @retval HAL status
3030   */
3031 HAL_StatusTypeDef HASH_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm)
3032 {
3033   uint32_t inputaddr;
3034   uint32_t inputSize;
3035   HAL_StatusTypeDef status ;
3036   HAL_HASH_StateTypeDef State_tmp = hhash->State;
3037 
3038   
3039   /* Make sure the input buffer size (in bytes) is a multiple of 4 when MDMAT bit is set
3040      (case of multi-buffer HASH processing) */
3041   assert_param(IS_HASH_DMA_MULTIBUFFER_SIZE(Size));
3042   
3043   /* If State is ready or suspended, start or resume polling-based HASH processing */
3044   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
3045   {
3046     /* Check input parameters */
3047     if ((pInBuffer == NULL) || (Size == 0U) ||
3048         /* Check phase coherency. Phase must be
3049            either READY (fresh start)
3050            or PROCESS (multi-buffer HASH management) */
3051         ((hhash->Phase != HAL_HASH_PHASE_READY) && (!(IS_HASH_PROCESSING(hhash)))))
3052     {
3053       hhash->State = HAL_HASH_STATE_READY;
3054       return  HAL_ERROR;
3055     }
3056 
3057 
3058     /* Process Locked */
3059     __HAL_LOCK(hhash);
3060 
3061     /* If not a resumption case */
3062     if (hhash->State == HAL_HASH_STATE_READY)
3063     {
3064       /* Change the HASH state */
3065       hhash->State = HAL_HASH_STATE_BUSY;
3066 
3067       /* Check if initialization phase has already been performed.
3068          If Phase is already set to HAL_HASH_PHASE_PROCESS, this means the
3069          API is processing a new input data message in case of multi-buffer HASH
3070          computation. */
3071       if (hhash->Phase == HAL_HASH_PHASE_READY)
3072       {
3073         /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
3074         MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT);
3075 
3076         /* Set the phase */
3077         hhash->Phase = HAL_HASH_PHASE_PROCESS;
3078       }
3079 
3080       /* Configure the Number of valid bits in last word of the message */
3081       __HAL_HASH_SET_NBVALIDBITS(Size);
3082 
3083       inputaddr = (uint32_t)pInBuffer;     /* DMA transfer start address   */
3084       inputSize = Size;                    /* DMA transfer size (in bytes) */
3085 
3086       /* In case of suspension request, save the starting parameters */
3087       hhash->pHashInBuffPtr =  pInBuffer;  /* DMA transfer start address   */
3088       hhash->HashInCount = Size;           /* DMA transfer size (in bytes) */
3089 
3090     }
3091     /* If resumption case */
3092     else
3093     {
3094       /* Change the HASH state */
3095       hhash->State = HAL_HASH_STATE_BUSY;
3096 
3097       /* Resumption case, inputaddr and inputSize are not set to the API input parameters
3098          but to those saved beforehand by HAL_HASH_DMAFeed_ProcessSuspend() when the
3099          processing was suspended */
3100       inputaddr = (uint32_t)hhash->pHashInBuffPtr;  /* DMA transfer start address   */
3101       inputSize = hhash->HashInCount;               /* DMA transfer size (in bytes) */
3102 
3103     }
3104 
3105     /* Set the HASH DMA transfer complete callback */
3106     hhash->hdmain->XferCpltCallback = HASH_DMAXferCplt;
3107     /* Set the DMA error callback */
3108     hhash->hdmain->XferErrorCallback = HASH_DMAError;
3109 
3110     /* Store number of words already pushed to manage proper DMA processing suspension */
3111     hhash->NbWordsAlreadyPushed = HASH_NBW_PUSHED();
3112 
3113     /* Enable the DMA In DMA stream */
3114     status = HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, \
3115                               (((inputSize % 4U) != 0U) ? ((inputSize + (4U - (inputSize % 4U))) / 4U) : \
3116                                (inputSize / 4U)));
3117 
3118     /* Enable DMA requests */
3119     SET_BIT(HASH->CR, HASH_CR_DMAE);
3120 
3121     /* Process Unlock */
3122     __HAL_UNLOCK(hhash);
3123 
3124     /* Return function status */
3125     if (status != HAL_OK)
3126     {
3127       /* Update HASH state machine to error */
3128       hhash->State = HAL_HASH_STATE_ERROR;
3129     }
3130 
3131     return status;
3132   }
3133   else
3134   {
3135     return HAL_BUSY;
3136   }
3137 }
3138 
3139 /**
3140   * @brief  Return the computed digest.
3141   * @note   The API waits for DCIS to be set then reads the computed digest.
3142   * @param  hhash HASH handle.
3143   * @param  pOutBuffer pointer to the computed digest.
3144   * @param  Timeout Timeout value.
3145   * @retval HAL status
3146   */
3147 HAL_StatusTypeDef HASH_Finish(HASH_HandleTypeDef *hhash, uint8_t *pOutBuffer, uint32_t Timeout)
3148 {
3149 
3150   if (hhash->State == HAL_HASH_STATE_READY)
3151   {
3152     /* Check parameter */
3153     if (pOutBuffer == NULL)
3154     {
3155       return  HAL_ERROR;
3156     }
3157 
3158     /* Process Locked */
3159     __HAL_LOCK(hhash);
3160 
3161     /* Change the HASH state to busy */
3162     hhash->State = HAL_HASH_STATE_BUSY;
3163 
3164     /* Wait for DCIS flag to be set */
3165     if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_DCIS, RESET, Timeout) != HAL_OK)
3166     {
3167       return HAL_TIMEOUT;
3168     }
3169 
3170     /* Read the message digest */
3171     HASH_GetDigest(pOutBuffer, HASH_DIGEST_LENGTH());
3172 
3173     /* Change the HASH state to ready */
3174     hhash->State = HAL_HASH_STATE_READY;
3175 
3176     /* Reset HASH state machine */
3177     hhash->Phase = HAL_HASH_PHASE_READY;
3178 
3179     /* Process UnLock */
3180     __HAL_UNLOCK(hhash);
3181 
3182     /* Return function status */
3183     return HAL_OK;
3184 
3185   }
3186   else
3187   {
3188     return HAL_BUSY;
3189   }
3190 
3191 }
3192 
3193 
3194 /**
3195   * @brief  Initialize the HASH peripheral in HMAC mode, next process pInBuffer then
3196   *         read the computed digest.
3197   * @note   Digest is available in pOutBuffer.
3198   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
3199   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
3200   * @param  hhash HASH handle.
3201   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
3202   * @param  Size length of the input buffer in bytes.
3203   * @param  pOutBuffer pointer to the computed digest.
3204   * @param  Timeout Timeout value.
3205   * @param  Algorithm HASH algorithm.
3206   * @retval HAL status
3207   */
3208 HAL_StatusTypeDef HMAC_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer,
3209                              uint32_t Timeout, uint32_t Algorithm)
3210 {
3211   HAL_HASH_StateTypeDef State_tmp = hhash->State;
3212 
3213   /* If State is ready or suspended, start or resume polling-based HASH processing */
3214   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
3215   {
3216     /* Check input parameters */
3217     if ((pInBuffer == NULL) || (Size == 0U) || (hhash->Init.pKey == NULL) || (hhash->Init.KeySize == 0U)
3218         || (pOutBuffer == NULL))
3219     {
3220       hhash->State = HAL_HASH_STATE_READY;
3221       return  HAL_ERROR;
3222     }
3223 
3224     /* Process Locked */
3225     __HAL_LOCK(hhash);
3226 
3227     /* Change the HASH state */
3228     hhash->State = HAL_HASH_STATE_BUSY;
3229 
3230     /* Check if initialization phase has already be performed */
3231     if (hhash->Phase == HAL_HASH_PHASE_READY)
3232     {
3233       /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits */
3234       if (hhash->Init.KeySize > 64U)
3235       {
3236         MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
3237                    Algorithm | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT);
3238       }
3239       else
3240       {
3241         MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
3242                    Algorithm | HASH_ALGOMODE_HMAC | HASH_CR_INIT);
3243       }
3244       /* Set the phase to Step 1 */
3245       hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_1;
3246       /* Resort to hhash internal fields to feed the Peripheral.
3247          Parameters will be updated in case of suspension to contain the proper
3248          information at resumption time. */
3249       hhash->pHashOutBuffPtr  = pOutBuffer;            /* Output digest address    */
3250       hhash->pHashInBuffPtr   = pInBuffer;             /* Input data address, HMAC_Processing input
3251                                                           parameter for Step 2     */
3252       hhash->HashInCount      = Size;                  /* Input data size, HMAC_Processing input
3253                                                           parameter for Step 2        */
3254       hhash->HashBuffSize     = Size;                  /* Store the input buffer size for the whole HMAC process*/
3255       hhash->pHashKeyBuffPtr  = hhash->Init.pKey;      /* Key address, HMAC_Processing input parameter for Step
3256                                                           1 and Step 3 */
3257       hhash->HashKeyCount     = hhash->Init.KeySize;   /* Key size, HMAC_Processing input parameter for Step 1
3258                                                           and Step 3    */
3259     }
3260 
3261     /* Carry out HMAC processing */
3262     return HMAC_Processing(hhash, Timeout);
3263 
3264   }
3265   else
3266   {
3267     return HAL_BUSY;
3268   }
3269 }
3270 
3271 
3272 
3273 /**
3274   * @brief  Initialize the HASH peripheral in HMAC mode, next process pInBuffer then
3275   *         read the computed digest in interruption mode.
3276   * @note   Digest is available in pOutBuffer.
3277   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
3278   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
3279   * @param  hhash HASH handle.
3280   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
3281   * @param  Size length of the input buffer in bytes.
3282   * @param  pOutBuffer pointer to the computed digest.
3283   * @param  Algorithm HASH algorithm.
3284   * @retval HAL status
3285   */
3286 HAL_StatusTypeDef HMAC_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer,
3287                                 uint32_t Algorithm)
3288 {
3289   HAL_HASH_StateTypeDef State_tmp = hhash->State;
3290 
3291   /* If State is ready or suspended, start or resume IT-based HASH processing */
3292   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
3293   {
3294     /* Check input parameters */
3295     if ((pInBuffer == NULL) || (Size == 0U) || (hhash->Init.pKey == NULL) || (hhash->Init.KeySize == 0U)
3296         || (pOutBuffer == NULL))
3297     {
3298       hhash->State = HAL_HASH_STATE_READY;
3299       return  HAL_ERROR;
3300     }
3301 
3302     /* Process Locked */
3303     __HAL_LOCK(hhash);
3304 
3305     /* Change the HASH state */
3306     hhash->State = HAL_HASH_STATE_BUSY;
3307 
3308     /* Initialize IT counter */
3309     hhash->HashITCounter = 1;
3310 
3311     /* Check if initialization phase has already be performed */
3312     if (hhash->Phase == HAL_HASH_PHASE_READY)
3313     {
3314       /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits */
3315       if (hhash->Init.KeySize > 64U)
3316       {
3317         MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
3318                    Algorithm | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT);
3319       }
3320       else
3321       {
3322         MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
3323                    Algorithm | HASH_ALGOMODE_HMAC | HASH_CR_INIT);
3324       }
3325 
3326       /* Resort to hhash internal fields hhash->pHashInBuffPtr and hhash->HashInCount
3327          to feed the Peripheral whatever the HMAC step.
3328          Lines below are set to start HMAC Step 1 processing where key is entered first. */
3329       hhash->HashInCount     = hhash->Init.KeySize; /* Key size                      */
3330       hhash->pHashInBuffPtr  = hhash->Init.pKey ;   /* Key address                   */
3331 
3332       /* Store input and output parameters in handle fields to manage steps transition
3333          or possible HMAC suspension/resumption */
3334       hhash->pHashKeyBuffPtr = hhash->Init.pKey;    /* Key address                   */
3335       hhash->pHashMsgBuffPtr = pInBuffer;           /* Input message address         */
3336       hhash->HashBuffSize    = Size;                /* Input message size (in bytes) */
3337       hhash->pHashOutBuffPtr = pOutBuffer;          /* Output digest address         */
3338 
3339       /* Configure the number of valid bits in last word of the key */
3340       __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
3341 
3342       /* Set the phase to Step 1 */
3343       hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_1;
3344     }
3345     else if ((hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1) || (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3))
3346     {
3347       /* Restart IT-based HASH processing after Step 1 or Step 3 suspension */
3348 
3349     }
3350     else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)
3351     {
3352       /* Restart IT-based HASH processing after Step 2 suspension */
3353 
3354     }
3355     else
3356     {
3357       /* Error report as phase incorrect */
3358       /* Process Unlock */
3359       __HAL_UNLOCK(hhash);
3360       hhash->State = HAL_HASH_STATE_READY;
3361       return HAL_ERROR;
3362     }
3363 
3364     /* Process Unlock */
3365     __HAL_UNLOCK(hhash);
3366 
3367     /* Enable Interrupts */
3368     __HAL_HASH_ENABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
3369 
3370     /* Return function status */
3371     return HAL_OK;
3372   }
3373   else
3374   {
3375     return HAL_BUSY;
3376   }
3377 
3378 }
3379 
3380 
3381 
3382 /**
3383   * @brief  Initialize the HASH peripheral in HMAC mode then initiate the required
3384   *         DMA transfers to feed the key and the input buffer to the Peripheral.
3385   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
3386   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
3387   * @note   In case of multi-buffer HMAC processing, the input buffer size (in bytes) must
3388   *         be a multiple of 4 otherwise, the HASH digest computation is corrupted.
3389   *         Only the length of the last buffer of the thread doesn't have to be a
3390   *         multiple of 4.
3391   * @param  hhash HASH handle.
3392   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
3393   * @param  Size length of the input buffer in bytes.
3394   * @param  Algorithm HASH algorithm.
3395   * @retval HAL status
3396   */
3397 HAL_StatusTypeDef HMAC_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm)
3398 {
3399   uint32_t inputaddr;
3400   uint32_t inputSize;
3401   HAL_StatusTypeDef status ;
3402   HAL_HASH_StateTypeDef State_tmp = hhash->State;
3403   /* Make sure the input buffer size (in bytes) is a multiple of 4 when digest calculation
3404      is disabled (multi-buffer HMAC processing, MDMAT bit to be set) */
3405   assert_param(IS_HMAC_DMA_MULTIBUFFER_SIZE(hhash, Size));
3406   /* If State is ready or suspended, start or resume DMA-based HASH processing */
3407   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
3408   {
3409     /* Check input parameters */
3410     if ((pInBuffer == NULL) || (Size == 0U) || (hhash->Init.pKey == NULL) || (hhash->Init.KeySize == 0U) ||
3411         /* Check phase coherency. Phase must be
3412             either READY (fresh start)
3413             or one of HMAC PROCESS steps (multi-buffer HASH management) */
3414         ((hhash->Phase != HAL_HASH_PHASE_READY) && (!(IS_HMAC_PROCESSING(hhash)))))
3415     {
3416       hhash->State = HAL_HASH_STATE_READY;
3417       return  HAL_ERROR;
3418     }
3419 
3420 
3421     /* Process Locked */
3422     __HAL_LOCK(hhash);
3423 
3424     /* If not a case of resumption after suspension */
3425     if (hhash->State == HAL_HASH_STATE_READY)
3426     {
3427       /* Check whether or not initialization phase has already be performed */
3428       if (hhash->Phase == HAL_HASH_PHASE_READY)
3429       {
3430         /* Change the HASH state */
3431         hhash->State = HAL_HASH_STATE_BUSY;
3432         /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits.
3433            At the same time, ensure MDMAT bit is cleared. */
3434         if (hhash->Init.KeySize > 64U)
3435         {
3436           MODIFY_REG(HASH->CR, HASH_CR_MDMAT | HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
3437                      Algorithm | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT);
3438         }
3439         else
3440         {
3441           MODIFY_REG(HASH->CR, HASH_CR_MDMAT | HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
3442                      Algorithm | HASH_ALGOMODE_HMAC | HASH_CR_INIT);
3443         }
3444         /* Store input aparameters in handle fields to manage steps transition
3445            or possible HMAC suspension/resumption */
3446         hhash->HashInCount = hhash->Init.KeySize;   /* Initial size for first DMA transfer (key size)      */
3447         hhash->pHashKeyBuffPtr = hhash->Init.pKey;  /* Key address                                         */
3448         hhash->pHashInBuffPtr  = hhash->Init.pKey ; /* First address passed to DMA (key address at Step 1) */
3449         hhash->pHashMsgBuffPtr = pInBuffer;         /* Input data address                                  */
3450         hhash->HashBuffSize = Size;                 /* input data size (in bytes)                          */
3451 
3452         /* Set DMA input parameters */
3453         inputaddr = (uint32_t)(hhash->Init.pKey);   /* Address passed to DMA (start by entering Key message) */
3454         inputSize = hhash->Init.KeySize;            /* Size for first DMA transfer (in bytes) */
3455 
3456         /* Configure the number of valid bits in last word of the key */
3457         __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
3458 
3459         /* Set the phase to Step 1 */
3460         hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_1;
3461 
3462       }
3463       else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)
3464       {
3465         /* Process a new input data message in case of multi-buffer HMAC processing
3466           (this is not a resumption case) */
3467 
3468         /* Change the HASH state */
3469         hhash->State = HAL_HASH_STATE_BUSY;
3470 
3471         /* Save input parameters to be able to manage possible suspension/resumption */
3472         hhash->HashInCount = Size;                /* Input message address       */
3473         hhash->pHashInBuffPtr = pInBuffer;        /* Input message size in bytes */
3474 
3475         /* Set DMA input parameters */
3476         inputaddr = (uint32_t)pInBuffer;           /* Input message address       */
3477         inputSize = Size;                          /* Input message size in bytes */
3478 
3479         if (hhash->DigestCalculationDisable == RESET)
3480         {
3481           /* This means this is the last buffer of the multi-buffer sequence: DCAL needs to be set. */
3482           __HAL_HASH_RESET_MDMAT();
3483           __HAL_HASH_SET_NBVALIDBITS(inputSize);
3484         }
3485       }
3486       else
3487       {
3488         /* Phase not aligned with handle READY state */
3489         __HAL_UNLOCK(hhash);
3490         /* Return function status */
3491         return HAL_ERROR;
3492       }
3493     }
3494     else
3495     {
3496       /* Resumption case (phase may be Step 1, 2 or 3) */
3497 
3498       /* Change the HASH state */
3499       hhash->State = HAL_HASH_STATE_BUSY;
3500 
3501       /* Set DMA input parameters at resumption location;
3502          inputaddr and inputSize are not set to the API input parameters
3503          but to those saved beforehand by HAL_HASH_DMAFeed_ProcessSuspend() when the
3504          processing was suspended. */
3505       inputaddr = (uint32_t)(hhash->pHashInBuffPtr);  /* Input message address       */
3506       inputSize = hhash->HashInCount;                 /* Input message size in bytes */
3507     }
3508 
3509 
3510     /* Set the HASH DMA transfer complete callback */
3511     hhash->hdmain->XferCpltCallback = HASH_DMAXferCplt;
3512     /* Set the DMA error callback */
3513     hhash->hdmain->XferErrorCallback = HASH_DMAError;
3514 
3515     /* Store number of words already pushed to manage proper DMA processing suspension */
3516     hhash->NbWordsAlreadyPushed = HASH_NBW_PUSHED();
3517 
3518     /* Enable the DMA In DMA stream */
3519     status = HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN,  \
3520                               (((inputSize % 4U) != 0U) ? ((inputSize + (4U - (inputSize % 4U))) / 4U) \
3521                                : (inputSize / 4U)));
3522 
3523     /* Enable DMA requests */
3524     SET_BIT(HASH->CR, HASH_CR_DMAE);
3525 
3526     /* Process Unlocked */
3527     __HAL_UNLOCK(hhash);
3528 
3529     /* Return function status */
3530     if (status != HAL_OK)
3531     {
3532       /* Update HASH state machine to error */
3533       hhash->State = HAL_HASH_STATE_ERROR;
3534     }
3535 
3536     /* Return function status */
3537     return status;
3538   }
3539   else
3540   {
3541     return HAL_BUSY;
3542   }
3543 }
3544 /**
3545   * @}
3546   */
3547 
3548 #endif /* HAL_HASH_MODULE_ENABLED */
3549 
3550 /**
3551   * @}
3552   */
3553 #endif /*  HASH*/
3554 /**
3555   * @}
3556   */
3557