STM32H735xx HAL User Manual
stm32h7xx_hal_hash.c
Go to the documentation of this file.
00001 /**
00002   ******************************************************************************
00003   * @file    stm32h7xx_hal_hash.c
00004   * @author  MCD Application Team
00005   * @brief   HASH HAL module driver.
00006   *          This file provides firmware functions to manage the following
00007   *          functionalities of the HASH peripheral:
00008   *           + Initialization and de-initialization methods
00009   *           + HASH or HMAC processing in polling mode
00010   *           + HASH or HMAC processing in interrupt mode
00011   *           + HASH or HMAC processing in DMA mode
00012   *           + Peripheral State methods
00013   *           + HASH or HMAC processing suspension/resumption
00014   *
00015   ******************************************************************************
00016   * @attention
00017   *
00018   * Copyright (c) 2017 STMicroelectronics.
00019   * All rights reserved.
00020   *
00021   * This software is licensed under terms that can be found in the LICENSE file
00022   * in the root directory of this software component.
00023   * If no LICENSE file comes with this software, it is provided AS-IS.
00024   *
00025   ******************************************************************************
00026   @verbatim
00027  ===============================================================================
00028                      ##### How to use this driver #####
00029  ===============================================================================
00030     [..]
00031     The HASH HAL driver can be used as follows:
00032 
00033     (#)Initialize the HASH low level resources by implementing the HAL_HASH_MspInit():
00034         (##) Enable the HASH interface clock using __HASH_CLK_ENABLE()
00035         (##) When resorting to interrupt-based APIs (e.g. HAL_HASH_xxx_Start_IT())
00036             (+++) Configure the HASH interrupt priority using HAL_NVIC_SetPriority()
00037             (+++) Enable the HASH IRQ handler using HAL_NVIC_EnableIRQ()
00038             (+++) In HASH IRQ handler, call HAL_HASH_IRQHandler() API
00039         (##) When resorting to DMA-based APIs  (e.g. HAL_HASH_xxx_Start_DMA())
00040             (+++) Enable the DMAx interface clock using
00041                    __DMAx_CLK_ENABLE()
00042             (+++) Configure and enable one DMA stream to manage data transfer from
00043                 memory to peripheral (input stream). Managing data transfer from
00044                 peripheral to memory can be performed only using CPU.
00045             (+++) Associate the initialized DMA handle to the HASH DMA handle
00046                 using  __HAL_LINKDMA()
00047             (+++) Configure the priority and enable the NVIC for the transfer complete
00048                 interrupt on the DMA stream: use
00049                  HAL_NVIC_SetPriority() and
00050                  HAL_NVIC_EnableIRQ()
00051 
00052     (#)Initialize the HASH HAL using HAL_HASH_Init(). This function:
00053         (##) resorts to HAL_HASH_MspInit() for low-level initialization,
00054         (##) configures the data type: 1-bit, 8-bit, 16-bit or 32-bit.
00055 
00056     (#)Three processing schemes are available:
00057         (##) Polling mode: processing APIs are blocking functions
00058              i.e. they process the data and wait till the digest computation is finished,
00059              e.g. HAL_HASH_xxx_Start() for HASH or HAL_HMAC_xxx_Start() for HMAC
00060         (##) Interrupt mode: processing APIs are not blocking functions
00061                 i.e. they process the data under interrupt,
00062                 e.g. HAL_HASH_xxx_Start_IT() for HASH or HAL_HMAC_xxx_Start_IT() for HMAC
00063         (##) DMA mode: processing APIs are not blocking functions and the CPU is
00064              not used for data transfer i.e. the data transfer is ensured by DMA,
00065                 e.g. HAL_HASH_xxx_Start_DMA() for HASH or HAL_HMAC_xxx_Start_DMA()
00066                 for HMAC. Note that in DMA mode, a call to HAL_HASH_xxx_Finish()
00067                 is then required to retrieve the digest.
00068 
00069     (#)When the processing function is called after HAL_HASH_Init(), the HASH peripheral is
00070        initialized and processes the buffer fed in input. When the input data have all been
00071        fed to the Peripheral, the digest computation can start.
00072 
00073     (#)Multi-buffer processing is possible in polling, interrupt and DMA modes.
00074         (##) In polling mode, only multi-buffer HASH processing is possible.
00075              API HAL_HASH_xxx_Accumulate() must be called for each input buffer, except for the last one.
00076              User must resort to HAL_HASH_xxx_Accumulate_End() to enter the last one and retrieve as
00077              well the computed digest.
00078 
00079         (##) In interrupt mode, API HAL_HASH_xxx_Accumulate_IT() must be called for each input buffer,
00080              except for the last one.
00081              User must resort to HAL_HASH_xxx_Accumulate_End_IT() to enter the last one and retrieve as
00082              well the computed digest.
00083 
00084         (##) In DMA mode, multi-buffer HASH and HMAC processing are possible.
00085               (+++) HASH processing: once initialization is done, MDMAT bit must be set
00086                through __HAL_HASH_SET_MDMAT() macro.
00087              From that point, each buffer can be fed to the Peripheral through HAL_HASH_xxx_Start_DMA() API.
00088              Before entering the last buffer, reset the MDMAT bit with __HAL_HASH_RESET_MDMAT()
00089              macro then wrap-up the HASH processing in feeding the last input buffer through the
00090              same API HAL_HASH_xxx_Start_DMA(). The digest can then be retrieved with a call to
00091              API HAL_HASH_xxx_Finish().
00092              (+++) HMAC processing (requires to resort to extended functions):
00093              after initialization, the key and the first input buffer are entered
00094              in the Peripheral with the API HAL_HMACEx_xxx_Step1_2_DMA(). This carries out HMAC step 1 and
00095              starts step 2.
00096              The following buffers are next entered with the API  HAL_HMACEx_xxx_Step2_DMA(). At this
00097              point, the HMAC processing is still carrying out step 2.
00098              Then, step 2 for the last input buffer and step 3 are carried out by a single call
00099              to HAL_HMACEx_xxx_Step2_3_DMA().
00100 
00101              The digest can finally be retrieved with a call to API HAL_HASH_xxx_Finish().
00102 
00103 
00104     (#)Context swapping.
00105         (##) Two APIs are available to suspend HASH or HMAC processing:
00106              (+++) HAL_HASH_SwFeed_ProcessSuspend() when data are entered by software (polling or IT mode),
00107              (+++) HAL_HASH_DMAFeed_ProcessSuspend() when data are entered by DMA.
00108 
00109         (##) When HASH or HMAC processing is suspended, HAL_HASH_ContextSaving() allows
00110             to save in memory the Peripheral context. This context can be restored afterwards
00111             to resume the HASH processing thanks to HAL_HASH_ContextRestoring().
00112 
00113         (##) Once the HASH Peripheral has been restored to the same configuration as that at suspension
00114              time, processing can be restarted with the same API call (same API, same handle,
00115              same parameters) as done before the suspension. Relevant parameters to restart at
00116              the proper location are internally saved in the HASH handle.
00117 
00118     (#)Call HAL_HASH_DeInit() to deinitialize the HASH peripheral.
00119 
00120      *** Remarks on message length ***
00121      ===================================
00122      [..]
00123       (#) HAL in interruption mode (interruptions driven)
00124 
00125         (##)Due to HASH peripheral hardware design, the peripheral interruption is triggered every 64 bytes.
00126         This is why, for driver implementation simplicity’s sake, user is requested to enter a message the
00127         length of which is a multiple of 4 bytes.
00128 
00129         (##) When the message length (in bytes) is not a multiple of words, a specific field exists in HASH_STR
00130         to specify which bits to discard at the end of the complete message to process only the message bits
00131         and not extra bits.
00132 
00133         (##) If user needs to perform a hash computation of a large input buffer that is spread around various places
00134         in memory and where each piece of this input buffer is not necessarily a multiple of 4 bytes in size, it becomes
00135         necessary to use a temporary buffer to format the data accordingly before feeding them to the Peripheral.
00136         It is advised to the user to
00137        (+++) achieve the first formatting operation by software then enter the data
00138        (+++) while the Peripheral is processing the first input set, carry out the second formatting
00139         operation by software, to be ready when DINIS occurs.
00140        (+++) repeat step 2 until the whole message is processed.
00141 
00142      [..]
00143       (#) HAL in DMA mode
00144 
00145         (##) Again, due to hardware design, the DMA transfer to feed the data can only be done on a word-basis.
00146         The same field described above in HASH_STR is used to specify which bits to discard at the end of the
00147         DMA transfer to process only the message bits and not extra bits. Due to hardware implementation,
00148         this is possible only at the end of the complete message. When several DMA transfers are needed to
00149         enter the message, this is not applicable at the end of the intermediary transfers.
00150 
00151         (##) Similarly to the interruption-driven mode, it is suggested to the user to format the consecutive
00152         chunks of data by software while the DMA transfer and processing is on-going for the first parts of
00153         the message. Due to the 32-bit alignment required for the DMA transfer, it is underlined that the
00154         software formatting operation is more complex than in the IT mode.
00155 
00156      *** Callback registration ***
00157      ===================================
00158      [..]
00159       (#) The compilation define  USE_HAL_HASH_REGISTER_CALLBACKS when set to 1
00160           allows the user to configure dynamically the driver callbacks.
00161           Use function HAL_HASH_RegisterCallback() to register a user callback.
00162 
00163       (#) Function HAL_HASH_RegisterCallback() allows to register following callbacks:
00164             (+) InCpltCallback    : callback for input completion.
00165             (+) DgstCpltCallback  : callback for digest computation completion.
00166             (+) ErrorCallback     : callback for error.
00167             (+) MspInitCallback   : HASH MspInit.
00168             (+) MspDeInitCallback : HASH MspDeInit.
00169           This function takes as parameters the HAL peripheral handle, the Callback ID
00170           and a pointer to the user callback function.
00171 
00172       (#) Use function HAL_HASH_UnRegisterCallback() to reset a callback to the default
00173           weak (surcharged) function.
00174           HAL_HASH_UnRegisterCallback() takes as parameters the HAL peripheral handle,
00175           and the Callback ID.
00176           This function allows to reset following callbacks:
00177             (+) InCpltCallback    : callback for input completion.
00178             (+) DgstCpltCallback  : callback for digest computation completion.
00179             (+) ErrorCallback     : callback for error.
00180             (+) MspInitCallback   : HASH MspInit.
00181             (+) MspDeInitCallback : HASH MspDeInit.
00182 
00183       (#) By default, after the HAL_HASH_Init and if the state is HAL_HASH_STATE_RESET
00184           all callbacks are reset to the corresponding legacy weak (surcharged) functions:
00185           examples HAL_HASH_InCpltCallback(), HAL_HASH_DgstCpltCallback()
00186           Exception done for MspInit and MspDeInit callbacks that are respectively
00187           reset to the legacy weak (surcharged) functions in the HAL_HASH_Init
00188           and HAL_HASH_DeInit only when these callbacks are null (not registered beforehand)
00189           If not, MspInit or MspDeInit are not null, the HAL_HASH_Init and HAL_HASH_DeInit
00190           keep and use the user MspInit/MspDeInit callbacks (registered beforehand).
00191 
00192           Callbacks can be registered/unregistered in READY state only.
00193           Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
00194           in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used
00195           during the Init/DeInit.
00196           In that case first register the MspInit/MspDeInit user callbacks
00197           using HAL_HASH_RegisterCallback before calling HAL_HASH_DeInit
00198           or HAL_HASH_Init function.
00199 
00200           When The compilation define USE_HAL_HASH_REGISTER_CALLBACKS is set to 0 or
00201           not defined, the callback registering feature is not available
00202           and weak (surcharged) callbacks are used.
00203 
00204   @endverbatim
00205   ******************************************************************************
00206   */
00207 
00208 /* Includes ------------------------------------------------------------------*/
00209 #include "stm32h7xx_hal.h"
00210 
00211 
00212 /** @addtogroup STM32H7xx_HAL_Driver
00213   * @{
00214   */
00215 #if defined (HASH)
00216 
00217 /** @defgroup HASH  HASH
00218   * @brief HASH HAL module driver.
00219   * @{
00220   */
00221 
00222 #ifdef HAL_HASH_MODULE_ENABLED
00223 
00224 /* Private typedef -----------------------------------------------------------*/
00225 /* Private define ------------------------------------------------------------*/
00226 /** @defgroup HASH_Private_Constants HASH Private Constants
00227   * @{
00228   */
00229 
00230 /** @defgroup HASH_Digest_Calculation_Status HASH Digest Calculation Status
00231   * @{
00232   */
00233 #define HASH_DIGEST_CALCULATION_NOT_STARTED       ((uint32_t)0x00000000U) /*!< DCAL not set after input data written in DIN register */
00234 #define HASH_DIGEST_CALCULATION_STARTED           ((uint32_t)0x00000001U) /*!< DCAL set after input data written in DIN register     */
00235 /**
00236   * @}
00237   */
00238 
00239 /** @defgroup HASH_Number_Of_CSR_Registers HASH Number of Context Swap Registers
00240   * @{
00241   */
00242 #define HASH_NUMBER_OF_CSR_REGISTERS              54U     /*!< Number of Context Swap Registers */
00243 /**
00244   * @}
00245   */
00246 
00247 /** @defgroup HASH_TimeOut_Value HASH TimeOut Value
00248   * @{
00249   */
00250 #define HASH_TIMEOUTVALUE                         1000U   /*!< Time-out value  */
00251 /**
00252   * @}
00253   */
00254 
00255 /** @defgroup HASH_DMA_Suspension_Words_Limit HASH DMA suspension words limit
00256   * @{
00257   */
00258 #define HASH_DMA_SUSPENSION_WORDS_LIMIT             20U   /*!< Number of words below which DMA suspension is aborted */
00259 /**
00260   * @}
00261   */
00262 
00263 /**
00264   * @}
00265   */
00266 
00267 /* Private macro -------------------------------------------------------------*/
00268 /* Private variables ---------------------------------------------------------*/
00269 /* Private function prototypes -----------------------------------------------*/
00270 /** @defgroup HASH_Private_Functions HASH Private Functions
00271   * @{
00272   */
00273 static void HASH_DMAXferCplt(DMA_HandleTypeDef *hdma);
00274 static void HASH_DMAError(DMA_HandleTypeDef *hdma);
00275 static void HASH_GetDigest(uint8_t *pMsgDigest, uint8_t Size);
00276 static HAL_StatusTypeDef HASH_WaitOnFlagUntilTimeout(HASH_HandleTypeDef *hhash, uint32_t Flag, FlagStatus Status,
00277                                                      uint32_t Timeout);
00278 static HAL_StatusTypeDef HASH_WriteData(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size);
00279 static HAL_StatusTypeDef HASH_IT(HASH_HandleTypeDef *hhash);
00280 static uint32_t HASH_Write_Block_Data(HASH_HandleTypeDef *hhash);
00281 static HAL_StatusTypeDef HMAC_Processing(HASH_HandleTypeDef *hhash, uint32_t Timeout);
00282 /**
00283   * @}
00284   */
00285 
00286 /** @defgroup HASH_Exported_Functions HASH Exported Functions
00287   * @{
00288   */
00289 
00290 /** @defgroup HASH_Exported_Functions_Group1 Initialization and de-initialization functions
00291   *  @brief    Initialization, configuration and call-back functions.
00292   *
00293 @verbatim
00294  ===============================================================================
00295               ##### Initialization and de-initialization functions #####
00296  ===============================================================================
00297     [..]  This section provides functions allowing to:
00298       (+) Initialize the HASH according to the specified parameters
00299           in the HASH_InitTypeDef and create the associated handle
00300       (+) DeInitialize the HASH peripheral
00301       (+) Initialize the HASH MCU Specific Package (MSP)
00302       (+) DeInitialize the HASH MSP
00303 
00304     [..]  This section provides as well call back functions definitions for user
00305           code to manage:
00306       (+) Input data transfer to Peripheral completion
00307       (+) Calculated digest retrieval completion
00308       (+) Error management
00309 
00310 
00311 
00312 @endverbatim
00313   * @{
00314   */
00315 
00316 /**
00317   * @brief  Initialize the HASH according to the specified parameters in the
00318             HASH_HandleTypeDef and create the associated handle.
00319   * @note   Only MDMAT and DATATYPE bits of HASH Peripheral are set by HAL_HASH_Init(),
00320   *         other configuration bits are set by HASH or HMAC processing APIs.
00321   * @note   MDMAT bit is systematically reset by HAL_HASH_Init(). To set it for
00322   *         multi-buffer HASH processing, user needs to resort to
00323   *         __HAL_HASH_SET_MDMAT() macro. For HMAC multi-buffer processing, the
00324   *         relevant APIs manage themselves the MDMAT bit.
00325   * @param  hhash HASH handle
00326   * @retval HAL status
00327   */
00328 HAL_StatusTypeDef HAL_HASH_Init(HASH_HandleTypeDef *hhash)
00329 {
00330   /* Check the hash handle allocation */
00331   if (hhash == NULL)
00332   {
00333     return HAL_ERROR;
00334   }
00335 
00336   /* Check the parameters */
00337   assert_param(IS_HASH_DATATYPE(hhash->Init.DataType));
00338 
00339 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
00340   if (hhash->State == HAL_HASH_STATE_RESET)
00341   {
00342     /* Allocate lock resource and initialize it */
00343     hhash->Lock = HAL_UNLOCKED;
00344 
00345     /* Reset Callback pointers in HAL_HASH_STATE_RESET only */
00346     hhash->InCpltCallback =  HAL_HASH_InCpltCallback;     /* Legacy weak (surcharged) input completion callback */
00347     hhash->DgstCpltCallback =  HAL_HASH_DgstCpltCallback; /* Legacy weak (surcharged) digest computation
00348                                                              completion callback */
00349     hhash->ErrorCallback =  HAL_HASH_ErrorCallback;       /* Legacy weak (surcharged) error callback */
00350     if (hhash->MspInitCallback == NULL)
00351     {
00352       hhash->MspInitCallback = HAL_HASH_MspInit;
00353     }
00354 
00355     /* Init the low level hardware */
00356     hhash->MspInitCallback(hhash);
00357   }
00358 #else
00359   if (hhash->State == HAL_HASH_STATE_RESET)
00360   {
00361     /* Allocate lock resource and initialize it */
00362     hhash->Lock = HAL_UNLOCKED;
00363 
00364     /* Init the low level hardware */
00365     HAL_HASH_MspInit(hhash);
00366   }
00367 #endif /* (USE_HAL_HASH_REGISTER_CALLBACKS) */
00368 
00369   /* Change the HASH state */
00370   hhash->State = HAL_HASH_STATE_BUSY;
00371 
00372   /* Reset HashInCount, HashITCounter, HashBuffSize and NbWordsAlreadyPushed */
00373   hhash->HashInCount = 0;
00374   hhash->HashBuffSize = 0;
00375   hhash->HashITCounter = 0;
00376   hhash->NbWordsAlreadyPushed = 0;
00377   /* Reset digest calculation bridle (MDMAT bit control) */
00378   hhash->DigestCalculationDisable = RESET;
00379   /* Set phase to READY */
00380   hhash->Phase = HAL_HASH_PHASE_READY;
00381   /* Reset suspension request flag */
00382   hhash->SuspendRequest = HAL_HASH_SUSPEND_NONE;
00383 
00384   /* Set the data type bit */
00385   MODIFY_REG(HASH->CR, HASH_CR_DATATYPE, hhash->Init.DataType);
00386   /* Reset MDMAT bit */
00387   __HAL_HASH_RESET_MDMAT();
00388   /* Reset HASH handle status */
00389   hhash->Status = HAL_OK;
00390 
00391   /* Set the HASH state to Ready */
00392   hhash->State = HAL_HASH_STATE_READY;
00393 
00394   /* Initialise the error code */
00395   hhash->ErrorCode = HAL_HASH_ERROR_NONE;
00396 
00397   /* Return function status */
00398   return HAL_OK;
00399 }
00400 
00401 /**
00402   * @brief  DeInitialize the HASH peripheral.
00403   * @param  hhash HASH handle.
00404   * @retval HAL status
00405   */
00406 HAL_StatusTypeDef HAL_HASH_DeInit(HASH_HandleTypeDef *hhash)
00407 {
00408   /* Check the HASH handle allocation */
00409   if (hhash == NULL)
00410   {
00411     return HAL_ERROR;
00412   }
00413 
00414   /* Change the HASH state */
00415   hhash->State = HAL_HASH_STATE_BUSY;
00416 
00417   /* Set the default HASH phase */
00418   hhash->Phase = HAL_HASH_PHASE_READY;
00419 
00420   /* Reset HashInCount, HashITCounter and HashBuffSize */
00421   hhash->HashInCount = 0;
00422   hhash->HashBuffSize = 0;
00423   hhash->HashITCounter = 0;
00424   /* Reset digest calculation bridle (MDMAT bit control) */
00425   hhash->DigestCalculationDisable = RESET;
00426 
00427 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
00428   if (hhash->MspDeInitCallback == NULL)
00429   {
00430     hhash->MspDeInitCallback = HAL_HASH_MspDeInit;
00431   }
00432 
00433   /* DeInit the low level hardware */
00434   hhash->MspDeInitCallback(hhash);
00435 #else
00436   /* DeInit the low level hardware: CLOCK, NVIC */
00437   HAL_HASH_MspDeInit(hhash);
00438 #endif /* (USE_HAL_HASH_REGISTER_CALLBACKS) */
00439 
00440 
00441   /* Reset HASH handle status */
00442   hhash->Status = HAL_OK;
00443 
00444   /* Set the HASH state to Ready */
00445   hhash->State = HAL_HASH_STATE_RESET;
00446 
00447   /* Initialise the error code */
00448   hhash->ErrorCode = HAL_HASH_ERROR_NONE;
00449 
00450   /* Reset multi buffers accumulation flag */
00451   hhash->Accumulation = 0U;
00452 
00453   /* Return function status */
00454   return HAL_OK;
00455 }
00456 
00457 /**
00458   * @brief  Initialize the HASH MSP.
00459   * @param  hhash HASH handle.
00460   * @retval None
00461   */
00462 __weak void HAL_HASH_MspInit(HASH_HandleTypeDef *hhash)
00463 {
00464   /* Prevent unused argument(s) compilation warning */
00465   UNUSED(hhash);
00466 
00467   /* NOTE : This function should not be modified; when the callback is needed,
00468             HAL_HASH_MspInit() can be implemented in the user file.
00469    */
00470 }
00471 
00472 /**
00473   * @brief  DeInitialize the HASH MSP.
00474   * @param  hhash HASH handle.
00475   * @retval None
00476   */
00477 __weak void HAL_HASH_MspDeInit(HASH_HandleTypeDef *hhash)
00478 {
00479   /* Prevent unused argument(s) compilation warning */
00480   UNUSED(hhash);
00481 
00482   /* NOTE : This function should not be modified; when the callback is needed,
00483             HAL_HASH_MspDeInit() can be implemented in the user file.
00484    */
00485 }
00486 
00487 /**
00488   * @brief  Input data transfer complete call back.
00489   * @note   HAL_HASH_InCpltCallback() is called when the complete input message
00490   *         has been fed to the Peripheral. This API is invoked only when input data are
00491   *         entered under interruption or through DMA.
00492   * @note   In case of HASH or HMAC multi-buffer DMA feeding case (MDMAT bit set),
00493   *         HAL_HASH_InCpltCallback() is called at the end of each buffer feeding
00494   *         to the Peripheral.
00495   * @param  hhash HASH handle.
00496   * @retval None
00497   */
00498 __weak void HAL_HASH_InCpltCallback(HASH_HandleTypeDef *hhash)
00499 {
00500   /* Prevent unused argument(s) compilation warning */
00501   UNUSED(hhash);
00502 
00503   /* NOTE : This function should not be modified; when the callback is needed,
00504             HAL_HASH_InCpltCallback() can be implemented in the user file.
00505    */
00506 }
00507 
00508 /**
00509   * @brief  Digest computation complete call back.
00510   * @note   HAL_HASH_DgstCpltCallback() is used under interruption, is not
00511   *         relevant with DMA.
00512   * @param  hhash HASH handle.
00513   * @retval None
00514   */
00515 __weak void HAL_HASH_DgstCpltCallback(HASH_HandleTypeDef *hhash)
00516 {
00517   /* Prevent unused argument(s) compilation warning */
00518   UNUSED(hhash);
00519 
00520   /* NOTE : This function should not be modified; when the callback is needed,
00521             HAL_HASH_DgstCpltCallback() can be implemented in the user file.
00522    */
00523 }
00524 
00525 /**
00526   * @brief  Error callback.
00527   * @note   Code user can resort to hhash->Status (HAL_ERROR, HAL_TIMEOUT,...)
00528   *         to retrieve the error type.
00529   * @param  hhash HASH handle.
00530   * @retval None
00531   */
00532 __weak void HAL_HASH_ErrorCallback(HASH_HandleTypeDef *hhash)
00533 {
00534   /* Prevent unused argument(s) compilation warning */
00535   UNUSED(hhash);
00536 
00537   /* NOTE : This function should not be modified; when the callback is needed,
00538             HAL_HASH_ErrorCallback() can be implemented in the user file.
00539    */
00540 }
00541 
00542 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
00543 /**
00544   * @brief  Register a User HASH Callback
00545   *         To be used instead of the weak (surcharged) predefined callback
00546   * @param hhash HASH handle
00547   * @param CallbackID ID of the callback to be registered
00548   *        This parameter can be one of the following values:
00549   *          @arg @ref HAL_HASH_INPUTCPLT_CB_ID HASH input completion Callback ID
00550   *          @arg @ref HAL_HASH_DGSTCPLT_CB_ID HASH digest computation completion Callback ID
00551   *          @arg @ref HAL_HASH_ERROR_CB_ID HASH error Callback ID
00552   *          @arg @ref HAL_HASH_MSPINIT_CB_ID HASH MspInit callback ID
00553   *          @arg @ref HAL_HASH_MSPDEINIT_CB_ID HASH MspDeInit callback ID
00554   * @param pCallback pointer to the Callback function
00555   * @retval status
00556   */
00557 HAL_StatusTypeDef HAL_HASH_RegisterCallback(HASH_HandleTypeDef *hhash, HAL_HASH_CallbackIDTypeDef CallbackID,
00558                                             pHASH_CallbackTypeDef pCallback)
00559 {
00560   HAL_StatusTypeDef status = HAL_OK;
00561 
00562   if (pCallback == NULL)
00563   {
00564     /* Update the error code */
00565     hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
00566     return HAL_ERROR;
00567   }
00568   /* Process locked */
00569   __HAL_LOCK(hhash);
00570 
00571   if (HAL_HASH_STATE_READY == hhash->State)
00572   {
00573     switch (CallbackID)
00574     {
00575       case HAL_HASH_INPUTCPLT_CB_ID :
00576         hhash->InCpltCallback = pCallback;
00577         break;
00578 
00579       case HAL_HASH_DGSTCPLT_CB_ID :
00580         hhash->DgstCpltCallback = pCallback;
00581         break;
00582 
00583       case HAL_HASH_ERROR_CB_ID :
00584         hhash->ErrorCallback = pCallback;
00585         break;
00586 
00587       case HAL_HASH_MSPINIT_CB_ID :
00588         hhash->MspInitCallback = pCallback;
00589         break;
00590 
00591       case HAL_HASH_MSPDEINIT_CB_ID :
00592         hhash->MspDeInitCallback = pCallback;
00593         break;
00594 
00595       default :
00596         /* Update the error code */
00597         hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
00598         /* update return status */
00599         status =  HAL_ERROR;
00600         break;
00601     }
00602   }
00603   else if (HAL_HASH_STATE_RESET == hhash->State)
00604   {
00605     switch (CallbackID)
00606     {
00607       case HAL_HASH_MSPINIT_CB_ID :
00608         hhash->MspInitCallback = pCallback;
00609         break;
00610 
00611       case HAL_HASH_MSPDEINIT_CB_ID :
00612         hhash->MspDeInitCallback = pCallback;
00613         break;
00614 
00615       default :
00616         /* Update the error code */
00617         hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
00618         /* update return status */
00619         status =  HAL_ERROR;
00620         break;
00621     }
00622   }
00623   else
00624   {
00625     /* Update the error code */
00626     hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
00627     /* update return status */
00628     status =  HAL_ERROR;
00629   }
00630 
00631   /* Release Lock */
00632   __HAL_UNLOCK(hhash);
00633   return status;
00634 }
00635 
00636 /**
00637   * @brief  Unregister a HASH Callback
00638   *         HASH Callback is redirected to the weak (surcharged) predefined callback
00639   * @param hhash HASH handle
00640   * @param CallbackID ID of the callback to be unregistered
00641   *        This parameter can be one of the following values:
00642   *          @arg @ref HAL_HASH_INPUTCPLT_CB_ID HASH input completion Callback ID
00643   *          @arg @ref HAL_HASH_DGSTCPLT_CB_ID HASH digest computation completion Callback ID
00644   *          @arg @ref HAL_HASH_ERROR_CB_ID HASH error Callback ID
00645   *          @arg @ref HAL_HASH_MSPINIT_CB_ID HASH MspInit callback ID
00646   *          @arg @ref HAL_HASH_MSPDEINIT_CB_ID HASH MspDeInit callback ID
00647   * @retval status
00648   */
00649 HAL_StatusTypeDef HAL_HASH_UnRegisterCallback(HASH_HandleTypeDef *hhash, HAL_HASH_CallbackIDTypeDef CallbackID)
00650 {
00651   HAL_StatusTypeDef status = HAL_OK;
00652 
00653   /* Process locked */
00654   __HAL_LOCK(hhash);
00655 
00656   if (HAL_HASH_STATE_READY == hhash->State)
00657   {
00658     switch (CallbackID)
00659     {
00660       case HAL_HASH_INPUTCPLT_CB_ID :
00661         hhash->InCpltCallback = HAL_HASH_InCpltCallback;     /* Legacy weak (surcharged) input completion callback */
00662         break;
00663 
00664       case HAL_HASH_DGSTCPLT_CB_ID :
00665         hhash->DgstCpltCallback = HAL_HASH_DgstCpltCallback; /* Legacy weak (surcharged) digest computation
00666                                                                 completion callback */
00667         break;
00668 
00669       case HAL_HASH_ERROR_CB_ID :
00670         hhash->ErrorCallback = HAL_HASH_ErrorCallback;       /* Legacy weak (surcharged) error callback */
00671         break;
00672 
00673       case HAL_HASH_MSPINIT_CB_ID :
00674         hhash->MspInitCallback = HAL_HASH_MspInit;           /* Legacy weak (surcharged) Msp Init */
00675         break;
00676 
00677       case HAL_HASH_MSPDEINIT_CB_ID :
00678         hhash->MspDeInitCallback = HAL_HASH_MspDeInit;       /* Legacy weak (surcharged) Msp DeInit */
00679         break;
00680 
00681       default :
00682         /* Update the error code */
00683         hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
00684         /* update return status */
00685         status =  HAL_ERROR;
00686         break;
00687     }
00688   }
00689   else if (HAL_HASH_STATE_RESET == hhash->State)
00690   {
00691     switch (CallbackID)
00692     {
00693       case HAL_HASH_MSPINIT_CB_ID :
00694         hhash->MspInitCallback = HAL_HASH_MspInit;           /* Legacy weak (surcharged) Msp Init */
00695         break;
00696 
00697       case HAL_HASH_MSPDEINIT_CB_ID :
00698         hhash->MspDeInitCallback = HAL_HASH_MspDeInit;       /* Legacy weak (surcharged) Msp DeInit */
00699         break;
00700 
00701       default :
00702         /* Update the error code */
00703         hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
00704         /* update return status */
00705         status =  HAL_ERROR;
00706         break;
00707     }
00708   }
00709   else
00710   {
00711     /* Update the error code */
00712     hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
00713     /* update return status */
00714     status =  HAL_ERROR;
00715   }
00716 
00717   /* Release Lock */
00718   __HAL_UNLOCK(hhash);
00719   return status;
00720 }
00721 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
00722 
00723 /**
00724   * @}
00725   */
00726 
00727 /** @defgroup HASH_Exported_Functions_Group2 HASH processing functions in polling mode
00728   *  @brief   HASH processing functions using polling mode.
00729   *
00730 @verbatim
00731  ===============================================================================
00732                  ##### Polling mode HASH processing functions #####
00733  ===============================================================================
00734     [..]  This section provides functions allowing to calculate in polling mode
00735           the hash value using one of the following algorithms:
00736       (+) MD5
00737          (++) HAL_HASH_MD5_Start()
00738          (++) HAL_HASH_MD5_Accmlt()
00739          (++) HAL_HASH_MD5_Accmlt_End()
00740       (+) SHA1
00741          (++) HAL_HASH_SHA1_Start()
00742          (++) HAL_HASH_SHA1_Accmlt()
00743          (++) HAL_HASH_SHA1_Accmlt_End()
00744 
00745     [..] For a single buffer to be hashed, user can resort to HAL_HASH_xxx_Start().
00746 
00747     [..]  In case of multi-buffer HASH processing (a single digest is computed while
00748           several buffers are fed to the Peripheral), the user can resort to successive calls
00749           to HAL_HASH_xxx_Accumulate() and wrap-up the digest computation by a call
00750           to HAL_HASH_xxx_Accumulate_End().
00751 
00752 @endverbatim
00753   * @{
00754   */
00755 
00756 /**
00757   * @brief  Initialize the HASH peripheral in MD5 mode, next process pInBuffer then
00758   *         read the computed digest.
00759   * @note   Digest is available in pOutBuffer.
00760   * @param  hhash HASH handle.
00761   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
00762   * @param  Size length of the input buffer in bytes.
00763   * @param  pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
00764   * @param  Timeout Timeout value
00765   * @retval HAL status
00766   */
00767 HAL_StatusTypeDef HAL_HASH_MD5_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer,
00768                                      uint32_t Timeout)
00769 {
00770   return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_MD5);
00771 }
00772 
00773 /**
00774   * @brief  If not already done, initialize the HASH peripheral in MD5 mode then
00775   *         processes pInBuffer.
00776   * @note   Consecutive calls to HAL_HASH_MD5_Accmlt() can be used to feed
00777   *         several input buffers back-to-back to the Peripheral that will yield a single
00778   *         HASH signature once all buffers have been entered. Wrap-up of input
00779   *         buffers feeding and retrieval of digest is done by a call to
00780   *         HAL_HASH_MD5_Accmlt_End().
00781   * @note   Field hhash->Phase of HASH handle is tested to check whether or not
00782   *         the Peripheral has already been initialized.
00783   * @note   Digest is not retrieved by this API, user must resort to HAL_HASH_MD5_Accmlt_End()
00784   *         to read it, feeding at the same time the last input buffer to the Peripheral.
00785   * @note   The input buffer size (in bytes) must be a multiple of 4 otherwise, the
00786   *         HASH digest computation is corrupted. Only HAL_HASH_MD5_Accmlt_End() is able
00787   *         to manage the ending buffer with a length in bytes not a multiple of 4.
00788   * @param  hhash HASH handle.
00789   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
00790   * @param  Size length of the input buffer in bytes, must be a multiple of 4.
00791   * @retval HAL status
00792   */
00793 HAL_StatusTypeDef HAL_HASH_MD5_Accmlt(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
00794 {
00795   return  HASH_Accumulate(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5);
00796 }
00797 
00798 /**
00799   * @brief  End computation of a single HASH signature after several calls to HAL_HASH_MD5_Accmlt() API.
00800   * @note   Digest is available in pOutBuffer.
00801   * @param  hhash HASH handle.
00802   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
00803   * @param  Size length of the input buffer in bytes.
00804   * @param  pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
00805   * @param  Timeout Timeout value
00806   * @retval HAL status
00807   */
00808 HAL_StatusTypeDef HAL_HASH_MD5_Accmlt_End(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size,
00809                                           uint8_t *pOutBuffer, uint32_t Timeout)
00810 {
00811   return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_MD5);
00812 }
00813 
00814 /**
00815   * @brief  Initialize the HASH peripheral in SHA1 mode, next process pInBuffer then
00816   *         read the computed digest.
00817   * @note   Digest is available in pOutBuffer.
00818   * @param  hhash HASH handle.
00819   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
00820   * @param  Size length of the input buffer in bytes.
00821   * @param  pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
00822   * @param  Timeout Timeout value
00823   * @retval HAL status
00824   */
00825 HAL_StatusTypeDef HAL_HASH_SHA1_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer,
00826                                       uint32_t Timeout)
00827 {
00828   return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA1);
00829 }
00830 
00831 /**
00832   * @brief  If not already done, initialize the HASH peripheral in SHA1 mode then
00833   *         processes pInBuffer.
00834   * @note   Consecutive calls to HAL_HASH_SHA1_Accmlt() can be used to feed
00835   *         several input buffers back-to-back to the Peripheral that will yield a single
00836   *         HASH signature once all buffers have been entered. Wrap-up of input
00837   *         buffers feeding and retrieval of digest is done by a call to
00838   *         HAL_HASH_SHA1_Accmlt_End().
00839   * @note   Field hhash->Phase of HASH handle is tested to check whether or not
00840   *         the Peripheral has already been initialized.
00841   * @note   Digest is not retrieved by this API, user must resort to HAL_HASH_SHA1_Accmlt_End()
00842   *         to read it, feeding at the same time the last input buffer to the Peripheral.
00843   * @note   The input buffer size (in bytes) must be a multiple of 4 otherwise, the
00844   *         HASH digest computation is corrupted. Only HAL_HASH_SHA1_Accmlt_End() is able
00845   *         to manage the ending buffer with a length in bytes not a multiple of 4.
00846   * @param  hhash HASH handle.
00847   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
00848   * @param  Size length of the input buffer in bytes, must be a multiple of 4.
00849   * @retval HAL status
00850   */
00851 HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
00852 {
00853   return  HASH_Accumulate(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1);
00854 }
00855 
00856 /**
00857   * @brief  End computation of a single HASH signature after several calls to HAL_HASH_SHA1_Accmlt() API.
00858   * @note   Digest is available in pOutBuffer.
00859   * @param  hhash HASH handle.
00860   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
00861   * @param  Size length of the input buffer in bytes.
00862   * @param  pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
00863   * @param  Timeout Timeout value
00864   * @retval HAL status
00865   */
00866 HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt_End(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size,
00867                                            uint8_t *pOutBuffer, uint32_t Timeout)
00868 {
00869   return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA1);
00870 }
00871 
00872 /**
00873   * @}
00874   */
00875 
00876 /** @defgroup HASH_Exported_Functions_Group3 HASH processing functions in interrupt mode
00877   *  @brief   HASH processing functions using interrupt mode.
00878   *
00879 @verbatim
00880  ===============================================================================
00881                  ##### Interruption mode HASH processing functions #####
00882  ===============================================================================
00883     [..]  This section provides functions allowing to calculate in interrupt mode
00884           the hash value using one of the following algorithms:
00885       (+) MD5
00886          (++) HAL_HASH_MD5_Start_IT()
00887          (++) HAL_HASH_MD5_Accmlt_IT()
00888          (++) HAL_HASH_MD5_Accmlt_End_IT()
00889       (+) SHA1
00890          (++) HAL_HASH_SHA1_Start_IT()
00891          (++) HAL_HASH_SHA1_Accmlt_IT()
00892          (++) HAL_HASH_SHA1_Accmlt_End_IT()
00893 
00894     [..]  API HAL_HASH_IRQHandler() manages each HASH interruption.
00895 
00896     [..] Note that HAL_HASH_IRQHandler() manages as well HASH Peripheral interruptions when in
00897          HMAC processing mode.
00898 
00899 
00900 @endverbatim
00901   * @{
00902   */
00903 
00904 /**
00905   * @brief  Initialize the HASH peripheral in MD5 mode, next process pInBuffer then
00906   *         read the computed digest in interruption mode.
00907   * @note   Digest is available in pOutBuffer.
00908   * @param  hhash HASH handle.
00909   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
00910   * @param  Size length of the input buffer in bytes.
00911   * @param  pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
00912   * @retval HAL status
00913   */
00914 HAL_StatusTypeDef HAL_HASH_MD5_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size,
00915                                         uint8_t *pOutBuffer)
00916 {
00917   return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_MD5);
00918 }
00919 
00920 /**
00921   * @brief  If not already done, initialize the HASH peripheral in MD5 mode then
00922   *         processes pInBuffer in interruption mode.
00923   * @note   Consecutive calls to HAL_HASH_MD5_Accmlt_IT() can be used to feed
00924   *         several input buffers back-to-back to the Peripheral that will yield a single
00925   *         HASH signature once all buffers have been entered. Wrap-up of input
00926   *         buffers feeding and retrieval of digest is done by a call to
00927   *         HAL_HASH_MD5_Accmlt_End_IT().
00928   * @note   Field hhash->Phase of HASH handle is tested to check whether or not
00929   *         the Peripheral has already been initialized.
00930   * @note   The input buffer size (in bytes) must be a multiple of 4 otherwise, the
00931   *         HASH digest computation is corrupted. Only HAL_HASH_MD5_Accmlt_End_IT() is able
00932   *         to manage the ending buffer with a length in bytes not a multiple of 4.
00933   * @param  hhash HASH handle.
00934   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
00935   * @param  Size length of the input buffer in bytes, must be a multiple of 4.
00936   * @retval HAL status
00937   */
00938 HAL_StatusTypeDef HAL_HASH_MD5_Accmlt_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
00939 {
00940   return  HASH_Accumulate_IT(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5);
00941 }
00942 
00943 /**
00944   * @brief  End computation of a single HASH signature after several calls to HAL_HASH_MD5_Accmlt_IT() API.
00945   * @note   Digest is available in pOutBuffer.
00946   * @param  hhash HASH handle.
00947   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
00948   * @param  Size length of the input buffer in bytes.
00949   * @param  pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
00950   * @retval HAL status
00951   */
00952 HAL_StatusTypeDef HAL_HASH_MD5_Accmlt_End_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size,
00953                                              uint8_t *pOutBuffer)
00954 {
00955   return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_MD5);
00956 }
00957 
00958 /**
00959   * @brief  Initialize the HASH peripheral in SHA1 mode, next process pInBuffer then
00960   *         read the computed digest in interruption mode.
00961   * @note   Digest is available in pOutBuffer.
00962   * @param  hhash HASH handle.
00963   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
00964   * @param  Size length of the input buffer in bytes.
00965   * @param  pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
00966   * @retval HAL status
00967   */
00968 HAL_StatusTypeDef HAL_HASH_SHA1_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size,
00969                                          uint8_t *pOutBuffer)
00970 {
00971   return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_SHA1);
00972 }
00973 
00974 
00975 /**
00976   * @brief  If not already done, initialize the HASH peripheral in SHA1 mode then
00977   *         processes pInBuffer in interruption mode.
00978   * @note   Consecutive calls to HAL_HASH_SHA1_Accmlt_IT() can be used to feed
00979   *         several input buffers back-to-back to the Peripheral that will yield a single
00980   *         HASH signature once all buffers have been entered. Wrap-up of input
00981   *         buffers feeding and retrieval of digest is done by a call to
00982   *         HAL_HASH_SHA1_Accmlt_End_IT().
00983   * @note   Field hhash->Phase of HASH handle is tested to check whether or not
00984   *         the Peripheral has already been initialized.
00985   * @note   The input buffer size (in bytes) must be a multiple of 4 otherwise, the
00986   *         HASH digest computation is corrupted. Only HAL_HASH_SHA1_Accmlt_End_IT() is able
00987   *         to manage the ending buffer with a length in bytes not a multiple of 4.
00988   * @param  hhash HASH handle.
00989   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
00990   * @param  Size length of the input buffer in bytes, must be a multiple of 4.
00991   * @retval HAL status
00992   */
00993 HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
00994 {
00995   return  HASH_Accumulate_IT(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1);
00996 }
00997 
00998 /**
00999   * @brief  End computation of a single HASH signature after several calls to HAL_HASH_SHA1_Accmlt_IT() API.
01000   * @note   Digest is available in pOutBuffer.
01001   * @param  hhash HASH handle.
01002   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
01003   * @param  Size length of the input buffer in bytes.
01004   * @param  pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
01005   * @retval HAL status
01006   */
01007 HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt_End_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size,
01008                                               uint8_t *pOutBuffer)
01009 {
01010   return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_SHA1);
01011 }
01012 
01013 /**
01014   * @brief Handle HASH interrupt request.
01015   * @param hhash HASH handle.
01016   * @note  HAL_HASH_IRQHandler() handles interrupts in HMAC processing as well.
01017   * @note  In case of error reported during the HASH interruption processing,
01018   *        HAL_HASH_ErrorCallback() API is called so that user code can
01019   *        manage the error. The error type is available in hhash->Status field.
01020   * @retval None
01021   */
01022 void HAL_HASH_IRQHandler(HASH_HandleTypeDef *hhash)
01023 {
01024   hhash->Status = HASH_IT(hhash);
01025   if (hhash->Status != HAL_OK)
01026   {
01027     hhash->ErrorCode |= HAL_HASH_ERROR_IT;
01028 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
01029     hhash->ErrorCallback(hhash);
01030 #else
01031     HAL_HASH_ErrorCallback(hhash);
01032 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
01033     /* After error handling by code user, reset HASH handle HAL status */
01034     hhash->Status = HAL_OK;
01035   }
01036 }
01037 
01038 /**
01039   * @}
01040   */
01041 
01042 /** @defgroup HASH_Exported_Functions_Group4 HASH processing functions in DMA mode
01043   *  @brief   HASH processing functions using DMA mode.
01044   *
01045 @verbatim
01046  ===============================================================================
01047                     ##### DMA mode HASH processing functions #####
01048  ===============================================================================
01049     [..]  This section provides functions allowing to calculate in DMA mode
01050           the hash value using one of the following algorithms:
01051       (+) MD5
01052          (++) HAL_HASH_MD5_Start_DMA()
01053          (++) HAL_HASH_MD5_Finish()
01054       (+) SHA1
01055          (++) HAL_HASH_SHA1_Start_DMA()
01056          (++) HAL_HASH_SHA1_Finish()
01057 
01058     [..]  When resorting to DMA mode to enter the data in the Peripheral, user must resort
01059           to  HAL_HASH_xxx_Start_DMA() then read the resulting digest with
01060           HAL_HASH_xxx_Finish().
01061     [..]  In case of multi-buffer HASH processing, MDMAT bit must first be set before
01062           the successive calls to HAL_HASH_xxx_Start_DMA(). Then, MDMAT bit needs to be
01063           reset before the last call to HAL_HASH_xxx_Start_DMA(). Digest is finally
01064           retrieved thanks to HAL_HASH_xxx_Finish().
01065 
01066 @endverbatim
01067   * @{
01068   */
01069 
01070 /**
01071   * @brief  Initialize the HASH peripheral in MD5 mode then initiate a DMA transfer
01072   *         to feed the input buffer to the Peripheral.
01073   * @note   Once the DMA transfer is finished, HAL_HASH_MD5_Finish() API must
01074   *         be called to retrieve the computed digest.
01075   * @param  hhash HASH handle.
01076   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
01077   * @param  Size length of the input buffer in bytes.
01078   * @retval HAL status
01079   */
01080 HAL_StatusTypeDef HAL_HASH_MD5_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
01081 {
01082   return HASH_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5);
01083 }
01084 
01085 /**
01086   * @brief  Return the computed digest in MD5 mode.
01087   * @note   The API waits for DCIS to be set then reads the computed digest.
01088   * @note   HAL_HASH_MD5_Finish() can be used as well to retrieve the digest in
01089   *         HMAC MD5 mode.
01090   * @param  hhash HASH handle.
01091   * @param  pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
01092   * @param  Timeout Timeout value.
01093   * @retval HAL status
01094   */
01095 HAL_StatusTypeDef HAL_HASH_MD5_Finish(HASH_HandleTypeDef *hhash, uint8_t *pOutBuffer, uint32_t Timeout)
01096 {
01097   return HASH_Finish(hhash, pOutBuffer, Timeout);
01098 }
01099 
01100 /**
01101   * @brief  Initialize the HASH peripheral in SHA1 mode then initiate a DMA transfer
01102   *         to feed the input buffer to the Peripheral.
01103   * @note   Once the DMA transfer is finished, HAL_HASH_SHA1_Finish() API must
01104   *         be called to retrieve the computed digest.
01105   * @param  hhash HASH handle.
01106   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
01107   * @param  Size length of the input buffer in bytes.
01108   * @retval HAL status
01109   */
01110 HAL_StatusTypeDef HAL_HASH_SHA1_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
01111 {
01112   return HASH_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1);
01113 }
01114 
01115 
01116 /**
01117   * @brief  Return the computed digest in SHA1 mode.
01118   * @note   The API waits for DCIS to be set then reads the computed digest.
01119   * @note   HAL_HASH_SHA1_Finish() can be used as well to retrieve the digest in
01120   *         HMAC SHA1 mode.
01121   * @param  hhash HASH handle.
01122   * @param  pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
01123   * @param  Timeout Timeout value.
01124   * @retval HAL status
01125   */
01126 HAL_StatusTypeDef HAL_HASH_SHA1_Finish(HASH_HandleTypeDef *hhash, uint8_t *pOutBuffer, uint32_t Timeout)
01127 {
01128   return HASH_Finish(hhash, pOutBuffer, Timeout);
01129 }
01130 
01131 /**
01132   * @}
01133   */
01134 
01135 /** @defgroup HASH_Exported_Functions_Group5 HMAC processing functions in polling mode
01136   *  @brief   HMAC processing functions using polling mode.
01137   *
01138 @verbatim
01139  ===============================================================================
01140                  ##### Polling mode HMAC processing functions #####
01141  ===============================================================================
01142     [..]  This section provides functions allowing to calculate in polling mode
01143           the HMAC value using one of the following algorithms:
01144       (+) MD5
01145          (++) HAL_HMAC_MD5_Start()
01146       (+) SHA1
01147          (++) HAL_HMAC_SHA1_Start()
01148 
01149 
01150 @endverbatim
01151   * @{
01152   */
01153 
01154 /**
01155   * @brief  Initialize the HASH peripheral in HMAC MD5 mode, next process pInBuffer then
01156   *         read the computed digest.
01157   * @note   Digest is available in pOutBuffer.
01158   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
01159   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
01160   * @param  hhash HASH handle.
01161   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
01162   * @param  Size length of the input buffer in bytes.
01163   * @param  pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
01164   * @param  Timeout Timeout value.
01165   * @retval HAL status
01166   */
01167 HAL_StatusTypeDef HAL_HMAC_MD5_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer,
01168                                      uint32_t Timeout)
01169 {
01170   return HMAC_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_MD5);
01171 }
01172 
01173 /**
01174   * @brief  Initialize the HASH peripheral in HMAC SHA1 mode, next process pInBuffer then
01175   *         read the computed digest.
01176   * @note   Digest is available in pOutBuffer.
01177   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
01178   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
01179   * @param  hhash HASH handle.
01180   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
01181   * @param  Size length of the input buffer in bytes.
01182   * @param  pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
01183   * @param  Timeout Timeout value.
01184   * @retval HAL status
01185   */
01186 HAL_StatusTypeDef HAL_HMAC_SHA1_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer,
01187                                       uint32_t Timeout)
01188 {
01189   return HMAC_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA1);
01190 }
01191 
01192 /**
01193   * @}
01194   */
01195 
01196 
01197 /** @defgroup HASH_Exported_Functions_Group6 HMAC processing functions in interrupt mode
01198   *  @brief   HMAC processing functions using interrupt mode.
01199   *
01200 @verbatim
01201  ===============================================================================
01202                  ##### Interrupt mode HMAC processing functions #####
01203  ===============================================================================
01204     [..]  This section provides functions allowing to calculate in interrupt mode
01205           the HMAC value using one of the following algorithms:
01206       (+) MD5
01207          (++) HAL_HMAC_MD5_Start_IT()
01208       (+) SHA1
01209          (++) HAL_HMAC_SHA1_Start_IT()
01210 
01211 @endverbatim
01212   * @{
01213   */
01214 
01215 
01216 /**
01217   * @brief  Initialize the HASH peripheral in HMAC MD5 mode, next process pInBuffer then
01218   *         read the computed digest in interrupt mode.
01219   * @note   Digest is available in pOutBuffer.
01220   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
01221   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
01222   * @param  hhash HASH handle.
01223   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
01224   * @param  Size length of the input buffer in bytes.
01225   * @param  pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
01226   * @retval HAL status
01227   */
01228 HAL_StatusTypeDef HAL_HMAC_MD5_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size,
01229                                         uint8_t *pOutBuffer)
01230 {
01231   return  HMAC_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_MD5);
01232 }
01233 
01234 /**
01235   * @brief  Initialize the HASH peripheral in HMAC SHA1 mode, next process pInBuffer then
01236   *         read the computed digest in interrupt mode.
01237   * @note   Digest is available in pOutBuffer.
01238   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
01239   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
01240   * @param  hhash HASH handle.
01241   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
01242   * @param  Size length of the input buffer in bytes.
01243   * @param  pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
01244   * @retval HAL status
01245   */
01246 HAL_StatusTypeDef HAL_HMAC_SHA1_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size,
01247                                          uint8_t *pOutBuffer)
01248 {
01249   return  HMAC_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_SHA1);
01250 }
01251 
01252 /**
01253   * @}
01254   */
01255 
01256 
01257 
01258 /** @defgroup HASH_Exported_Functions_Group7 HMAC processing functions in DMA mode
01259   *  @brief   HMAC processing functions using DMA modes.
01260   *
01261 @verbatim
01262  ===============================================================================
01263                  ##### DMA mode HMAC processing functions #####
01264  ===============================================================================
01265     [..]  This section provides functions allowing to calculate in DMA mode
01266           the HMAC value using one of the following algorithms:
01267       (+) MD5
01268          (++) HAL_HMAC_MD5_Start_DMA()
01269       (+) SHA1
01270          (++) HAL_HMAC_SHA1_Start_DMA()
01271 
01272     [..]  When resorting to DMA mode to enter the data in the Peripheral for HMAC processing,
01273           user must resort to  HAL_HMAC_xxx_Start_DMA() then read the resulting digest
01274           with HAL_HASH_xxx_Finish().
01275 
01276 @endverbatim
01277   * @{
01278   */
01279 
01280 
01281 /**
01282   * @brief  Initialize the HASH peripheral in HMAC MD5 mode then initiate the required
01283   *         DMA transfers to feed the key and the input buffer to the Peripheral.
01284   * @note   Once the DMA transfers are finished (indicated by hhash->State set back
01285   *         to HAL_HASH_STATE_READY), HAL_HASH_MD5_Finish() API must be called to retrieve
01286   *         the computed digest.
01287   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
01288   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
01289   * @note   If MDMAT bit is set before calling this function (multi-buffer
01290   *          HASH processing case), the input buffer size (in bytes) must be
01291   *          a multiple of 4 otherwise, the HASH digest computation is corrupted.
01292   *          For the processing of the last buffer of the thread, MDMAT bit must
01293   *          be reset and the buffer length (in bytes) doesn't have to be a
01294   *          multiple of 4.
01295   * @param  hhash HASH handle.
01296   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
01297   * @param  Size length of the input buffer in bytes.
01298   * @retval HAL status
01299   */
01300 HAL_StatusTypeDef HAL_HMAC_MD5_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
01301 {
01302   return  HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5);
01303 }
01304 
01305 
01306 /**
01307   * @brief  Initialize the HASH peripheral in HMAC SHA1 mode then initiate the required
01308   *         DMA transfers to feed the key and the input buffer to the Peripheral.
01309   * @note   Once the DMA transfers are finished (indicated by hhash->State set back
01310   *         to HAL_HASH_STATE_READY), HAL_HASH_SHA1_Finish() API must be called to retrieve
01311   *         the computed digest.
01312   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
01313   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
01314   * @note   If MDMAT bit is set before calling this function (multi-buffer
01315   *          HASH processing case), the input buffer size (in bytes) must be
01316   *          a multiple of 4 otherwise, the HASH digest computation is corrupted.
01317   *          For the processing of the last buffer of the thread, MDMAT bit must
01318   *          be reset and the buffer length (in bytes) doesn't have to be a
01319   *          multiple of 4.
01320   * @param  hhash HASH handle.
01321   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
01322   * @param  Size length of the input buffer in bytes.
01323   * @retval HAL status
01324   */
01325 HAL_StatusTypeDef HAL_HMAC_SHA1_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
01326 {
01327   return  HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1);
01328 }
01329 
01330 /**
01331   * @}
01332   */
01333 
01334 /** @defgroup HASH_Exported_Functions_Group8 Peripheral states functions
01335   *  @brief   Peripheral State functions.
01336   *
01337 @verbatim
01338  ===============================================================================
01339                       ##### Peripheral State methods #####
01340  ===============================================================================
01341     [..]
01342     This section permits to get in run-time the state and the peripheral handle
01343     status of the peripheral:
01344       (+) HAL_HASH_GetState()
01345       (+) HAL_HASH_GetStatus()
01346 
01347     [..]
01348     Additionally, this subsection provides functions allowing to save and restore
01349     the HASH or HMAC processing context in case of calculation suspension:
01350       (+) HAL_HASH_ContextSaving()
01351       (+) HAL_HASH_ContextRestoring()
01352 
01353     [..]
01354     This subsection provides functions allowing to suspend the HASH processing
01355       (+) when input are fed to the Peripheral by software
01356           (++) HAL_HASH_SwFeed_ProcessSuspend()
01357       (+) when input are fed to the Peripheral by DMA
01358           (++) HAL_HASH_DMAFeed_ProcessSuspend()
01359 
01360 
01361 
01362 @endverbatim
01363   * @{
01364   */
01365 
01366 /**
01367   * @brief  Return the HASH handle state.
01368   * @note   The API yields the current state of the handle (BUSY, READY,...).
01369   * @param  hhash HASH handle.
01370   * @retval HAL HASH state
01371   */
01372 HAL_HASH_StateTypeDef HAL_HASH_GetState(HASH_HandleTypeDef *hhash)
01373 {
01374   return hhash->State;
01375 }
01376 
01377 
01378 /**
01379   * @brief Return the HASH HAL status.
01380   * @note  The API yields the HAL status of the handle: it is the result of the
01381   *        latest HASH processing and allows to report any issue (e.g. HAL_TIMEOUT).
01382   * @param  hhash HASH handle.
01383   * @retval HAL status
01384   */
01385 HAL_StatusTypeDef HAL_HASH_GetStatus(HASH_HandleTypeDef *hhash)
01386 {
01387   return hhash->Status;
01388 }
01389 
01390 /**
01391   * @brief  Save the HASH context in case of processing suspension.
01392   * @param  hhash HASH handle.
01393   * @param  pMemBuffer pointer to the memory buffer where the HASH context
01394   *         is saved.
01395   * @note   The IMR, STR, CR then all the CSR registers are saved
01396   *         in that order. Only the r/w bits are read to be restored later on.
01397   * @note   By default, all the context swap registers (there are
01398   *         HASH_NUMBER_OF_CSR_REGISTERS of those) are saved.
01399   * @note   pMemBuffer points to a buffer allocated by the user. The buffer size
01400   *         must be at least (HASH_NUMBER_OF_CSR_REGISTERS + 3) * 4 uint8 long.
01401   * @retval None
01402   */
01403 void HAL_HASH_ContextSaving(HASH_HandleTypeDef *hhash, uint8_t *pMemBuffer)
01404 {
01405   uint32_t mem_ptr = (uint32_t)pMemBuffer;
01406   uint32_t csr_ptr = (uint32_t)HASH->CSR;
01407   uint32_t i;
01408 
01409   /* Prevent unused argument(s) compilation warning */
01410   UNUSED(hhash);
01411 
01412   /* Save IMR register content */
01413   *(uint32_t *)(mem_ptr) = READ_BIT(HASH->IMR, HASH_IT_DINI | HASH_IT_DCI);
01414   mem_ptr += 4U;
01415   /* Save STR register content */
01416   *(uint32_t *)(mem_ptr) = READ_BIT(HASH->STR, HASH_STR_NBLW);
01417   mem_ptr += 4U;
01418   /* Save CR register content */
01419   *(uint32_t *)(mem_ptr) = READ_BIT(HASH->CR, HASH_CR_DMAE | HASH_CR_DATATYPE | HASH_CR_MODE | HASH_CR_ALGO |
01420                                     HASH_CR_LKEY | HASH_CR_MDMAT);
01421   mem_ptr += 4U;
01422   /* By default, save all CSRs registers */
01423   for (i = HASH_NUMBER_OF_CSR_REGISTERS; i > 0U; i--)
01424   {
01425     *(uint32_t *)(mem_ptr) = *(uint32_t *)(csr_ptr);
01426     mem_ptr += 4U;
01427     csr_ptr += 4U;
01428   }
01429 }
01430 
01431 
01432 /**
01433   * @brief  Restore the HASH context in case of processing resumption.
01434   * @param  hhash HASH handle.
01435   * @param  pMemBuffer pointer to the memory buffer where the HASH context
01436   *         is stored.
01437   * @note   The IMR, STR, CR then all the CSR registers are restored
01438   *         in that order. Only the r/w bits are restored.
01439   * @note   By default, all the context swap registers (HASH_NUMBER_OF_CSR_REGISTERS
01440   *         of those) are restored (all of them have been saved by default
01441   *         beforehand).
01442   * @retval None
01443   */
01444 void HAL_HASH_ContextRestoring(HASH_HandleTypeDef *hhash, uint8_t *pMemBuffer)
01445 {
01446   uint32_t mem_ptr = (uint32_t)pMemBuffer;
01447   uint32_t csr_ptr = (uint32_t)HASH->CSR;
01448   uint32_t i;
01449 
01450   /* Prevent unused argument(s) compilation warning */
01451   UNUSED(hhash);
01452 
01453   /* Restore IMR register content */
01454   WRITE_REG(HASH->IMR, (*(uint32_t *)(mem_ptr)));
01455   mem_ptr += 4U;
01456   /* Restore STR register content */
01457   WRITE_REG(HASH->STR, (*(uint32_t *)(mem_ptr)));
01458   mem_ptr += 4U;
01459   /* Restore CR register content */
01460   WRITE_REG(HASH->CR, (*(uint32_t *)(mem_ptr)));
01461   mem_ptr += 4U;
01462 
01463   /* Reset the HASH processor before restoring the Context
01464   Swap Registers (CSR) */
01465   __HAL_HASH_INIT();
01466 
01467   /* By default, restore all CSR registers */
01468   for (i = HASH_NUMBER_OF_CSR_REGISTERS; i > 0U; i--)
01469   {
01470     WRITE_REG((*(uint32_t *)(csr_ptr)), (*(uint32_t *)(mem_ptr)));
01471     mem_ptr += 4U;
01472     csr_ptr += 4U;
01473   }
01474 }
01475 
01476 
01477 /**
01478   * @brief  Initiate HASH processing suspension when in polling or interruption mode.
01479   * @param  hhash HASH handle.
01480   * @note   Set the handle field SuspendRequest to the appropriate value so that
01481   *         the on-going HASH processing is suspended as soon as the required
01482   *         conditions are met. Note that the actual suspension is carried out
01483   *         by the functions HASH_WriteData() in polling mode and HASH_IT() in
01484   *         interruption mode.
01485   * @retval None
01486   */
01487 void HAL_HASH_SwFeed_ProcessSuspend(HASH_HandleTypeDef *hhash)
01488 {
01489   /* Set Handle Suspend Request field */
01490   hhash->SuspendRequest = HAL_HASH_SUSPEND;
01491 }
01492 
01493 /**
01494   * @brief  Suspend the HASH processing when in DMA mode.
01495   * @param  hhash HASH handle.
01496   * @note   When suspension attempt occurs at the very end of a DMA transfer and
01497   *         all the data have already been entered in the Peripheral, hhash->State is
01498   *         set to HAL_HASH_STATE_READY and the API returns HAL_ERROR. It is
01499   *         recommended to wrap-up the processing in reading the digest as usual.
01500   * @retval HAL status
01501   */
01502 HAL_StatusTypeDef HAL_HASH_DMAFeed_ProcessSuspend(HASH_HandleTypeDef *hhash)
01503 {
01504   uint32_t tmp_remaining_DMATransferSize_inWords;
01505   uint32_t tmp_initial_DMATransferSize_inWords;
01506   uint32_t tmp_words_already_pushed;
01507 
01508   if (hhash->State == HAL_HASH_STATE_READY)
01509   {
01510     return HAL_ERROR;
01511   }
01512   else
01513   {
01514 
01515     /* Make sure there is enough time to suspend the processing */
01516     tmp_remaining_DMATransferSize_inWords = ((DMA_Stream_TypeDef *)hhash->hdmain->Instance)->NDTR;
01517 
01518     if (tmp_remaining_DMATransferSize_inWords <= HASH_DMA_SUSPENSION_WORDS_LIMIT)
01519     {
01520       /* No suspension attempted since almost to the end of the transferred data. */
01521       /* Best option for user code is to wrap up low priority message hashing     */
01522       return HAL_ERROR;
01523     }
01524 
01525     /* Wait for BUSY flag to be reset */
01526     if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK)
01527     {
01528       return HAL_TIMEOUT;
01529     }
01530 
01531     if (__HAL_HASH_GET_FLAG(HASH_FLAG_DCIS) != RESET)
01532     {
01533       return HAL_ERROR;
01534     }
01535 
01536     /* Wait for BUSY flag to be set */
01537     if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, RESET, HASH_TIMEOUTVALUE) != HAL_OK)
01538     {
01539       return HAL_TIMEOUT;
01540     }
01541     /* Disable DMA channel */
01542     /* Note that the Abort function will
01543       - Clear the transfer error flags
01544       - Unlock
01545       - Set the State
01546     */
01547     if (HAL_DMA_Abort(hhash->hdmain) != HAL_OK)
01548     {
01549       return HAL_ERROR;
01550     }
01551 
01552     /* Clear DMAE bit */
01553     CLEAR_BIT(HASH->CR, HASH_CR_DMAE);
01554 
01555     /* Wait for BUSY flag to be reset */
01556     if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK)
01557     {
01558       return HAL_TIMEOUT;
01559     }
01560 
01561     if (__HAL_HASH_GET_FLAG(HASH_FLAG_DCIS) != RESET)
01562     {
01563       return HAL_ERROR;
01564     }
01565 
01566     /* At this point, DMA interface is disabled and no transfer is on-going */
01567     /* Retrieve from the DMA handle how many words remain to be written */
01568     tmp_remaining_DMATransferSize_inWords = ((DMA_Stream_TypeDef *)hhash->hdmain->Instance)->NDTR;
01569 
01570     if (tmp_remaining_DMATransferSize_inWords == 0U)
01571     {
01572       /* All the DMA transfer is actually done. Suspension occurred at the very end
01573          of the transfer. Either the digest computation is about to start (HASH case)
01574          or processing is about to move from one step to another (HMAC case).
01575          In both cases, the processing can't be suspended at this point. It is
01576          safer to
01577          - retrieve the low priority block digest before starting the high
01578            priority block processing (HASH case)
01579          - re-attempt a new suspension (HMAC case)
01580          */
01581       return HAL_ERROR;
01582     }
01583     else
01584     {
01585 
01586       /* Compute how many words were supposed to be transferred by DMA */
01587       tmp_initial_DMATransferSize_inWords = (((hhash->HashInCount % 4U) != 0U) ? \
01588                                              ((hhash->HashInCount + 3U) / 4U) : (hhash->HashInCount / 4U));
01589 
01590       /* If discrepancy between the number of words reported by DMA Peripheral and
01591         the numbers of words entered as reported by HASH Peripheral, correct it */
01592       /* tmp_words_already_pushed reflects the number of words that were already pushed before
01593          the start of DMA transfer (multi-buffer processing case) */
01594       tmp_words_already_pushed = hhash->NbWordsAlreadyPushed;
01595       if (((tmp_words_already_pushed + tmp_initial_DMATransferSize_inWords - \
01596             tmp_remaining_DMATransferSize_inWords) % 16U) != HASH_NBW_PUSHED())
01597       {
01598         tmp_remaining_DMATransferSize_inWords--; /* one less word to be transferred again */
01599       }
01600 
01601       /* Accordingly, update the input pointer that points at the next word to be
01602          transferred to the Peripheral by DMA */
01603       hhash->pHashInBuffPtr +=  4U * (tmp_initial_DMATransferSize_inWords - tmp_remaining_DMATransferSize_inWords) ;
01604 
01605       /* And store in HashInCount the remaining size to transfer (in bytes) */
01606       hhash->HashInCount = 4U * tmp_remaining_DMATransferSize_inWords;
01607 
01608     }
01609 
01610     /* Set State as suspended */
01611     hhash->State = HAL_HASH_STATE_SUSPENDED;
01612 
01613     return HAL_OK;
01614 
01615   }
01616 }
01617 
01618 /**
01619   * @brief  Return the HASH handle error code.
01620   * @param  hhash pointer to a HASH_HandleTypeDef structure.
01621   * @retval HASH Error Code
01622   */
01623 uint32_t HAL_HASH_GetError(HASH_HandleTypeDef *hhash)
01624 {
01625   /* Return HASH Error Code */
01626   return hhash->ErrorCode;
01627 }
01628 /**
01629   * @}
01630   */
01631 
01632 
01633 /**
01634   * @}
01635   */
01636 
01637 /** @defgroup HASH_Private_Functions HASH Private Functions
01638   * @{
01639   */
01640 
01641 /**
01642   * @brief DMA HASH Input Data transfer completion callback.
01643   * @param hdma DMA handle.
01644   * @note  In case of HMAC processing, HASH_DMAXferCplt() initiates
01645   *        the next DMA transfer for the following HMAC step.
01646   * @retval None
01647   */
01648 static void HASH_DMAXferCplt(DMA_HandleTypeDef *hdma)
01649 {
01650   HASH_HandleTypeDef *hhash = (HASH_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
01651   uint32_t inputaddr;
01652   uint32_t buffersize;
01653   HAL_StatusTypeDef status = HAL_OK;
01654 
01655   if (hhash->State != HAL_HASH_STATE_SUSPENDED)
01656   {
01657 
01658     /* Disable the DMA transfer */
01659     CLEAR_BIT(HASH->CR, HASH_CR_DMAE);
01660 
01661     if (READ_BIT(HASH->CR, HASH_CR_MODE) == 0U)
01662     {
01663       /* If no HMAC processing, input data transfer is now over */
01664 
01665       /* Change the HASH state to ready */
01666       hhash->State = HAL_HASH_STATE_READY;
01667 
01668       /* Call Input data transfer complete call back */
01669 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
01670       hhash->InCpltCallback(hhash);
01671 #else
01672       HAL_HASH_InCpltCallback(hhash);
01673 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
01674 
01675     }
01676     else
01677     {
01678       /* HMAC processing: depending on the current HMAC step and whether or
01679       not multi-buffer processing is on-going, the next step is initiated
01680       and MDMAT bit is set.  */
01681 
01682 
01683       if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3)
01684       {
01685         /* This is the end of HMAC processing */
01686 
01687         /* Change the HASH state to ready */
01688         hhash->State = HAL_HASH_STATE_READY;
01689 
01690         /* Call Input data transfer complete call back
01691         (note that the last DMA transfer was that of the key
01692         for the outer HASH operation). */
01693 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
01694         hhash->InCpltCallback(hhash);
01695 #else
01696         HAL_HASH_InCpltCallback(hhash);
01697 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
01698 
01699         return;
01700       }
01701       else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1)
01702       {
01703         inputaddr = (uint32_t)hhash->pHashMsgBuffPtr;     /* DMA transfer start address */
01704         buffersize = hhash->HashBuffSize;                 /* DMA transfer size (in bytes) */
01705         hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_2;        /* Move phase from Step 1 to Step 2 */
01706 
01707         /* In case of suspension request, save the new starting parameters */
01708         hhash->HashInCount = hhash->HashBuffSize;         /* Initial DMA transfer size (in bytes) */
01709         hhash->pHashInBuffPtr  = hhash->pHashMsgBuffPtr ; /* DMA transfer start address           */
01710 
01711         hhash->NbWordsAlreadyPushed = 0U;                  /* Reset number of words already pushed */
01712         /* Check whether or not digest calculation must be disabled (in case of multi-buffer HMAC processing) */
01713         if (hhash->DigestCalculationDisable != RESET)
01714         {
01715           /* Digest calculation is disabled: Step 2 must start with MDMAT bit set,
01716           no digest calculation will be triggered at the end of the input buffer feeding to the Peripheral */
01717           __HAL_HASH_SET_MDMAT();
01718         }
01719       }
01720       else  /*case (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)*/
01721       {
01722         if (hhash->DigestCalculationDisable != RESET)
01723         {
01724           /* No automatic move to Step 3 as a new message buffer will be fed to the Peripheral
01725           (case of multi-buffer HMAC processing):
01726           DCAL must not be set.
01727           Phase remains in Step 2, MDMAT remains set at this point.
01728           Change the HASH state to ready and call Input data transfer complete call back. */
01729           hhash->State = HAL_HASH_STATE_READY;
01730 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
01731           hhash->InCpltCallback(hhash);
01732 #else
01733           HAL_HASH_InCpltCallback(hhash);
01734 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
01735           return ;
01736         }
01737         else
01738         {
01739           /* Digest calculation is not disabled (case of single buffer input or last buffer
01740           of multi-buffer HMAC processing) */
01741           inputaddr = (uint32_t)hhash->Init.pKey;       /* DMA transfer start address */
01742           buffersize = hhash->Init.KeySize;             /* DMA transfer size (in bytes) */
01743           hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_3;    /* Move phase from Step 2 to Step 3 */
01744           /* In case of suspension request, save the new starting parameters */
01745           hhash->HashInCount = hhash->Init.KeySize;     /* Initial size for second DMA transfer (input data) */
01746           hhash->pHashInBuffPtr  = hhash->Init.pKey ;   /* address passed to DMA, now entering data message */
01747 
01748           hhash->NbWordsAlreadyPushed = 0U;              /* Reset number of words already pushed */
01749         }
01750       }
01751 
01752       /* Configure the Number of valid bits in last word of the message */
01753       __HAL_HASH_SET_NBVALIDBITS(buffersize);
01754 
01755       /* Set the HASH DMA transfer completion call back */
01756       hhash->hdmain->XferCpltCallback = HASH_DMAXferCplt;
01757 
01758       /* Enable the DMA In DMA stream */
01759       status = HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, \
01760                                 (((buffersize % 4U) != 0U) ? ((buffersize + (4U - (buffersize % 4U))) / 4U) : \
01761                                  (buffersize / 4U)));
01762 
01763       /* Enable DMA requests */
01764       SET_BIT(HASH->CR, HASH_CR_DMAE);
01765 
01766       /* Return function status */
01767       if (status != HAL_OK)
01768       {
01769         /* Update HASH state machine to error */
01770         hhash->State = HAL_HASH_STATE_ERROR;
01771       }
01772       else
01773       {
01774         /* Change HASH state */
01775         hhash->State = HAL_HASH_STATE_BUSY;
01776       }
01777     }
01778   }
01779 
01780   return;
01781 }
01782 
01783 /**
01784   * @brief DMA HASH communication error callback.
01785   * @param hdma DMA handle.
01786   * @note  HASH_DMAError() callback invokes HAL_HASH_ErrorCallback() that
01787   *        can contain user code to manage the error.
01788   * @retval None
01789   */
01790 static void HASH_DMAError(DMA_HandleTypeDef *hdma)
01791 {
01792   HASH_HandleTypeDef *hhash = (HASH_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
01793 
01794   if (hhash->State != HAL_HASH_STATE_SUSPENDED)
01795   {
01796     hhash->ErrorCode |= HAL_HASH_ERROR_DMA;
01797     /* Set HASH state to ready to prevent any blocking issue in user code
01798        present in HAL_HASH_ErrorCallback() */
01799     hhash->State = HAL_HASH_STATE_READY;
01800     /* Set HASH handle status to error */
01801     hhash->Status = HAL_ERROR;
01802 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
01803     hhash->ErrorCallback(hhash);
01804 #else
01805     HAL_HASH_ErrorCallback(hhash);
01806 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
01807     /* After error handling by code user, reset HASH handle HAL status */
01808     hhash->Status = HAL_OK;
01809 
01810   }
01811 }
01812 
01813 /**
01814   * @brief  Feed the input buffer to the HASH Peripheral.
01815   * @param  hhash HASH handle.
01816   * @param  pInBuffer pointer to input buffer.
01817   * @param  Size the size of input buffer in bytes.
01818   * @note   HASH_WriteData() regularly reads hhash->SuspendRequest to check whether
01819   *         or not the HASH processing must be suspended. If this is the case, the
01820   *         processing is suspended when possible and the Peripheral feeding point reached at
01821   *         suspension time is stored in the handle for resumption later on.
01822   * @retval HAL status
01823   */
01824 static HAL_StatusTypeDef HASH_WriteData(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
01825 {
01826   uint32_t buffercounter;
01827   __IO uint32_t inputaddr = (uint32_t) pInBuffer;
01828 
01829   for (buffercounter = 0U; buffercounter < Size; buffercounter += 4U)
01830   {
01831     /* Write input data 4 bytes at a time */
01832     HASH->DIN = *(uint32_t *)inputaddr;
01833     inputaddr += 4U;
01834 
01835     /* If the suspension flag has been raised and if the processing is not about
01836     to end, suspend processing */
01837     if ((hhash->SuspendRequest == HAL_HASH_SUSPEND) && ((buffercounter + 4U) < Size))
01838     {
01839       /* wait for flag BUSY not set before  Wait for DINIS = 1*/
01840       if (buffercounter >= 64U)
01841       {
01842         if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK)
01843         {
01844           return HAL_TIMEOUT;
01845         }
01846       }
01847       /* Wait for DINIS = 1, which occurs when 16 32-bit locations are free
01848       in the input buffer */
01849       if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))
01850       {
01851         /* Reset SuspendRequest */
01852         hhash->SuspendRequest = HAL_HASH_SUSPEND_NONE;
01853 
01854         /* Depending whether the key or the input data were fed to the Peripheral, the feeding point
01855         reached at suspension time is not saved in the same handle fields */
01856         if ((hhash->Phase == HAL_HASH_PHASE_PROCESS) || (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2))
01857         {
01858           /* Save current reading and writing locations of Input and Output buffers */
01859           hhash->pHashInBuffPtr = (uint8_t *)inputaddr;
01860           /* Save the number of bytes that remain to be processed at this point */
01861           hhash->HashInCount    =  Size - (buffercounter + 4U);
01862         }
01863         else if ((hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1) || (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3))
01864         {
01865           /* Save current reading and writing locations of Input and Output buffers */
01866           hhash->pHashKeyBuffPtr  = (uint8_t *)inputaddr;
01867           /* Save the number of bytes that remain to be processed at this point */
01868           hhash->HashKeyCount  =  Size - (buffercounter + 4U);
01869         }
01870         else
01871         {
01872           /* Unexpected phase: unlock process and report error */
01873           hhash->State = HAL_HASH_STATE_READY;
01874           __HAL_UNLOCK(hhash);
01875           return HAL_ERROR;
01876         }
01877 
01878         /* Set the HASH state to Suspended and exit to stop entering data */
01879         hhash->State = HAL_HASH_STATE_SUSPENDED;
01880 
01881         return HAL_OK;
01882       } /* if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))  */
01883     } /* if ((hhash->SuspendRequest == HAL_HASH_SUSPEND) && ((buffercounter+4) < Size)) */
01884   }   /* for(buffercounter = 0; buffercounter < Size; buffercounter+=4)                 */
01885 
01886   /* At this point, all the data have been entered to the Peripheral: exit */
01887   return  HAL_OK;
01888 }
01889 
01890 /**
01891   * @brief  Retrieve the message digest.
01892   * @param  pMsgDigest pointer to the computed digest.
01893   * @param  Size message digest size in bytes.
01894   * @retval None
01895   */
01896 static void HASH_GetDigest(uint8_t *pMsgDigest, uint8_t Size)
01897 {
01898   uint32_t msgdigest = (uint32_t)pMsgDigest;
01899 
01900   switch (Size)
01901   {
01902     /* Read the message digest */
01903     case 16:  /* MD5 */
01904       *(uint32_t *)(msgdigest) = __REV(HASH->HR[0]);
01905       msgdigest += 4U;
01906       *(uint32_t *)(msgdigest) = __REV(HASH->HR[1]);
01907       msgdigest += 4U;
01908       *(uint32_t *)(msgdigest) = __REV(HASH->HR[2]);
01909       msgdigest += 4U;
01910       *(uint32_t *)(msgdigest) = __REV(HASH->HR[3]);
01911       break;
01912     case 20:  /* SHA1 */
01913       *(uint32_t *)(msgdigest) = __REV(HASH->HR[0]);
01914       msgdigest += 4U;
01915       *(uint32_t *)(msgdigest) = __REV(HASH->HR[1]);
01916       msgdigest += 4U;
01917       *(uint32_t *)(msgdigest) = __REV(HASH->HR[2]);
01918       msgdigest += 4U;
01919       *(uint32_t *)(msgdigest) = __REV(HASH->HR[3]);
01920       msgdigest += 4U;
01921       *(uint32_t *)(msgdigest) = __REV(HASH->HR[4]);
01922       break;
01923     case 28:  /* SHA224 */
01924       *(uint32_t *)(msgdigest) = __REV(HASH->HR[0]);
01925       msgdigest += 4U;
01926       *(uint32_t *)(msgdigest) = __REV(HASH->HR[1]);
01927       msgdigest += 4U;
01928       *(uint32_t *)(msgdigest) = __REV(HASH->HR[2]);
01929       msgdigest += 4U;
01930       *(uint32_t *)(msgdigest) = __REV(HASH->HR[3]);
01931       msgdigest += 4U;
01932       *(uint32_t *)(msgdigest) = __REV(HASH->HR[4]);
01933       msgdigest += 4U;
01934       *(uint32_t *)(msgdigest) = __REV(HASH_DIGEST->HR[5]);
01935       msgdigest += 4U;
01936       *(uint32_t *)(msgdigest) = __REV(HASH_DIGEST->HR[6]);
01937       break;
01938     case 32:   /* SHA256 */
01939       *(uint32_t *)(msgdigest) = __REV(HASH->HR[0]);
01940       msgdigest += 4U;
01941       *(uint32_t *)(msgdigest) = __REV(HASH->HR[1]);
01942       msgdigest += 4U;
01943       *(uint32_t *)(msgdigest) = __REV(HASH->HR[2]);
01944       msgdigest += 4U;
01945       *(uint32_t *)(msgdigest) = __REV(HASH->HR[3]);
01946       msgdigest += 4U;
01947       *(uint32_t *)(msgdigest) = __REV(HASH->HR[4]);
01948       msgdigest += 4U;
01949       *(uint32_t *)(msgdigest) = __REV(HASH_DIGEST->HR[5]);
01950       msgdigest += 4U;
01951       *(uint32_t *)(msgdigest) = __REV(HASH_DIGEST->HR[6]);
01952       msgdigest += 4U;
01953       *(uint32_t *)(msgdigest) = __REV(HASH_DIGEST->HR[7]);
01954       break;
01955     default:
01956       break;
01957   }
01958 }
01959 
01960 
01961 
01962 /**
01963   * @brief  Handle HASH processing Timeout.
01964   * @param  hhash HASH handle.
01965   * @param  Flag specifies the HASH flag to check.
01966   * @param  Status the Flag status (SET or RESET).
01967   * @param  Timeout Timeout duration.
01968   * @retval HAL status
01969   */
01970 static HAL_StatusTypeDef HASH_WaitOnFlagUntilTimeout(HASH_HandleTypeDef *hhash, uint32_t Flag, FlagStatus Status,
01971                                                      uint32_t Timeout)
01972 {
01973   uint32_t tickstart = HAL_GetTick();
01974 
01975   /* Wait until flag is set */
01976   if (Status == RESET)
01977   {
01978     while (__HAL_HASH_GET_FLAG(Flag) == RESET)
01979     {
01980       /* Check for the Timeout */
01981       if (Timeout != HAL_MAX_DELAY)
01982       {
01983         if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
01984         {
01985           /* Set State to Ready to be able to restart later on */
01986           hhash->State  = HAL_HASH_STATE_READY;
01987           /* Store time out issue in handle status */
01988           hhash->Status = HAL_TIMEOUT;
01989 
01990           /* Process Unlocked */
01991           __HAL_UNLOCK(hhash);
01992 
01993           return HAL_TIMEOUT;
01994         }
01995       }
01996     }
01997   }
01998   else
01999   {
02000     while (__HAL_HASH_GET_FLAG(Flag) != RESET)
02001     {
02002       /* Check for the Timeout */
02003       if (Timeout != HAL_MAX_DELAY)
02004       {
02005         if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
02006         {
02007           /* Set State to Ready to be able to restart later on */
02008           hhash->State  = HAL_HASH_STATE_READY;
02009           /* Store time out issue in handle status */
02010           hhash->Status = HAL_TIMEOUT;
02011 
02012           /* Process Unlocked */
02013           __HAL_UNLOCK(hhash);
02014 
02015           return HAL_TIMEOUT;
02016         }
02017       }
02018     }
02019   }
02020   return HAL_OK;
02021 }
02022 
02023 
02024 /**
02025   * @brief  HASH processing in interruption mode.
02026   * @param  hhash HASH handle.
02027   * @note   HASH_IT() regularly reads hhash->SuspendRequest to check whether
02028   *         or not the HASH processing must be suspended. If this is the case, the
02029   *         processing is suspended when possible and the Peripheral feeding point reached at
02030   *         suspension time is stored in the handle for resumption later on.
02031   * @retval HAL status
02032   */
02033 static HAL_StatusTypeDef HASH_IT(HASH_HandleTypeDef *hhash)
02034 {
02035   if (hhash->State == HAL_HASH_STATE_BUSY)
02036   {
02037     /* ITCounter must not be equal to 0 at this point. Report an error if this is the case. */
02038     if (hhash->HashITCounter == 0U)
02039     {
02040       /* Disable Interrupts */
02041       __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
02042       /* HASH state set back to Ready to prevent any issue in user code
02043          present in HAL_HASH_ErrorCallback() */
02044       hhash->State = HAL_HASH_STATE_READY;
02045       return HAL_ERROR;
02046     }
02047     else if (hhash->HashITCounter == 1U)
02048     {
02049       /* This is the first call to HASH_IT, the first input data are about to be
02050          entered in the Peripheral. A specific processing is carried out at this point to
02051          start-up the processing. */
02052       hhash->HashITCounter = 2U;
02053     }
02054     else
02055     {
02056       /* Cruise speed reached, HashITCounter remains equal to 3 until the end of
02057         the HASH processing or the end of the current step for HMAC processing. */
02058       hhash->HashITCounter = 3U;
02059     }
02060 
02061     /* If digest is ready */
02062     if (__HAL_HASH_GET_FLAG(HASH_FLAG_DCIS))
02063     {
02064       /* Read the digest */
02065       HASH_GetDigest(hhash->pHashOutBuffPtr, HASH_DIGEST_LENGTH());
02066 
02067       /* Disable Interrupts */
02068       __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
02069       /* Change the HASH state */
02070       hhash->State = HAL_HASH_STATE_READY;
02071       /* Reset HASH state machine */
02072       hhash->Phase = HAL_HASH_PHASE_READY;
02073       /* Call digest computation complete call back */
02074 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
02075       hhash->DgstCpltCallback(hhash);
02076 #else
02077       HAL_HASH_DgstCpltCallback(hhash);
02078 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
02079 
02080       return HAL_OK;
02081     }
02082 
02083     /* If Peripheral ready to accept new data */
02084     if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))
02085     {
02086 
02087       /* If the suspension flag has been raised and if the processing is not about
02088          to end, suspend processing */
02089       if ((hhash->HashInCount != 0U) && (hhash->SuspendRequest == HAL_HASH_SUSPEND))
02090       {
02091         /* Disable Interrupts */
02092         __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
02093 
02094         /* Reset SuspendRequest */
02095         hhash->SuspendRequest = HAL_HASH_SUSPEND_NONE;
02096 
02097         /* Change the HASH state */
02098         hhash->State = HAL_HASH_STATE_SUSPENDED;
02099 
02100         return HAL_OK;
02101       }
02102 
02103       /* Enter input data in the Peripheral through HASH_Write_Block_Data() call and
02104         check whether the digest calculation has been triggered */
02105       if (HASH_Write_Block_Data(hhash) == HASH_DIGEST_CALCULATION_STARTED)
02106       {
02107         /* Call Input data transfer complete call back
02108            (called at the end of each step for HMAC) */
02109 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
02110         hhash->InCpltCallback(hhash);
02111 #else
02112         HAL_HASH_InCpltCallback(hhash);
02113 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
02114 
02115         if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1)
02116         {
02117           /* Wait until Peripheral is not busy anymore */
02118           if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK)
02119           {
02120             /* Disable Interrupts */
02121             __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
02122             return HAL_TIMEOUT;
02123           }
02124           /* Initialization start for HMAC STEP 2 */
02125           hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_2;        /* Move phase from Step 1 to Step 2 */
02126           __HAL_HASH_SET_NBVALIDBITS(hhash->HashBuffSize);  /* Set NBLW for the input message */
02127           hhash->HashInCount = hhash->HashBuffSize;         /* Set the input data size (in bytes) */
02128           hhash->pHashInBuffPtr = hhash->pHashMsgBuffPtr;   /* Set the input data address */
02129           hhash->HashITCounter = 1;                         /* Set ITCounter to 1 to indicate the start
02130                                                                of a new phase */
02131           __HAL_HASH_ENABLE_IT(HASH_IT_DINI);               /* Enable IT (was disabled in HASH_Write_Block_Data) */
02132         }
02133         else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)
02134         {
02135           /* Wait until Peripheral is not busy anymore */
02136           if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK)
02137           {
02138             /* Disable Interrupts */
02139             __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
02140             return HAL_TIMEOUT;
02141           }
02142           /* Initialization start for HMAC STEP 3 */
02143           hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_3;         /* Move phase from Step 2 to Step 3 */
02144           __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);   /* Set NBLW for the key */
02145           hhash->HashInCount = hhash->Init.KeySize;          /* Set the key size (in bytes) */
02146           hhash->pHashInBuffPtr = hhash->Init.pKey;          /* Set the key address */
02147           hhash->HashITCounter = 1;                          /* Set ITCounter to 1 to indicate the start
02148                                                                 of a new phase */
02149           __HAL_HASH_ENABLE_IT(HASH_IT_DINI);                /* Enable IT (was disabled in HASH_Write_Block_Data) */
02150         }
02151         else
02152         {
02153           /* Nothing to do */
02154         }
02155       } /* if (HASH_Write_Block_Data(hhash) == HASH_DIGEST_CALCULATION_STARTED) */
02156     }  /* if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))*/
02157 
02158     /* Return function status */
02159     return HAL_OK;
02160   }
02161   else
02162   {
02163     return HAL_BUSY;
02164   }
02165 }
02166 
02167 
02168 /**
02169   * @brief  Write a block of data in HASH Peripheral in interruption mode.
02170   * @param  hhash HASH handle.
02171   * @note   HASH_Write_Block_Data() is called under interruption by HASH_IT().
02172   * @retval HAL status
02173   */
02174 static uint32_t HASH_Write_Block_Data(HASH_HandleTypeDef *hhash)
02175 {
02176   uint32_t inputaddr;
02177   uint32_t buffercounter;
02178   uint32_t inputcounter;
02179   uint32_t ret = HASH_DIGEST_CALCULATION_NOT_STARTED;
02180 
02181   /* If there are more than 64 bytes remaining to be entered */
02182   if (hhash->HashInCount > 64U)
02183   {
02184     inputaddr = (uint32_t)hhash->pHashInBuffPtr;
02185     /* Write the Input block in the Data IN register
02186       (16 32-bit words, or 64 bytes are entered) */
02187     for (buffercounter = 0U; buffercounter < 64U; buffercounter += 4U)
02188     {
02189       HASH->DIN = *(uint32_t *)inputaddr;
02190       inputaddr += 4U;
02191     }
02192     /* If this is the start of input data entering, an additional word
02193       must be entered to start up the HASH processing */
02194     if (hhash->HashITCounter == 2U)
02195     {
02196       HASH->DIN = *(uint32_t *)inputaddr;
02197       if (hhash->HashInCount >= 68U)
02198       {
02199         /* There are still data waiting to be entered in the Peripheral.
02200            Decrement buffer counter and set pointer to the proper
02201            memory location for the next data entering round. */
02202         hhash->HashInCount -= 68U;
02203         hhash->pHashInBuffPtr += 68U;
02204       }
02205       else
02206       {
02207         /* All the input buffer has been fed to the HW. */
02208         hhash->HashInCount = 0U;
02209       }
02210     }
02211     else
02212     {
02213       /* 64 bytes have been entered and there are still some remaining:
02214          Decrement buffer counter and set pointer to the proper
02215         memory location for the next data entering round.*/
02216       hhash->HashInCount -= 64U;
02217       hhash->pHashInBuffPtr += 64U;
02218     }
02219   }
02220   else
02221   {
02222     /* 64 or less bytes remain to be entered. This is the last
02223       data entering round. */
02224 
02225     /* Get the buffer address */
02226     inputaddr = (uint32_t)hhash->pHashInBuffPtr;
02227     /* Get the buffer counter */
02228     inputcounter = hhash->HashInCount;
02229     /* Disable Interrupts */
02230     __HAL_HASH_DISABLE_IT(HASH_IT_DINI);
02231 
02232     /* Write the Input block in the Data IN register */
02233     for (buffercounter = 0U; buffercounter < ((inputcounter + 3U) / 4U); buffercounter++)
02234     {
02235       HASH->DIN = *(uint32_t *)inputaddr;
02236       inputaddr += 4U;
02237     }
02238 
02239     if (hhash->Accumulation == 1U)
02240     {
02241       /* Field accumulation is set, API only feeds data to the Peripheral and under interruption.
02242          The digest computation will be started when the last buffer data are entered. */
02243 
02244       /* Reset multi buffers accumulation flag */
02245       hhash->Accumulation = 0U;
02246       /* Change the HASH state */
02247       hhash->State = HAL_HASH_STATE_READY;
02248       /* Call Input data transfer complete call back */
02249 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
02250       hhash->InCpltCallback(hhash);
02251 #else
02252       HAL_HASH_InCpltCallback(hhash);
02253 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
02254     }
02255     else
02256     {
02257       /* Start the Digest calculation */
02258       __HAL_HASH_START_DIGEST();
02259       /* Return indication that digest calculation has started:
02260          this return value triggers the call to Input data transfer
02261          complete call back as well as the proper transition from
02262          one step to another in HMAC mode. */
02263       ret = HASH_DIGEST_CALCULATION_STARTED;
02264     }
02265     /* Reset buffer counter */
02266     hhash->HashInCount = 0;
02267   }
02268 
02269   /* Return whether or digest calculation has started */
02270   return ret;
02271 }
02272 
02273 /**
02274   * @brief  HMAC processing in polling mode.
02275   * @param  hhash HASH handle.
02276   * @param  Timeout Timeout value.
02277   * @retval HAL status
02278   */
02279 static HAL_StatusTypeDef HMAC_Processing(HASH_HandleTypeDef *hhash, uint32_t Timeout)
02280 {
02281   /* Ensure first that Phase is correct */
02282   if ((hhash->Phase != HAL_HASH_PHASE_HMAC_STEP_1) && (hhash->Phase != HAL_HASH_PHASE_HMAC_STEP_2)
02283       && (hhash->Phase != HAL_HASH_PHASE_HMAC_STEP_3))
02284   {
02285     /* Change the HASH state */
02286     hhash->State = HAL_HASH_STATE_READY;
02287 
02288     /* Process Unlock */
02289     __HAL_UNLOCK(hhash);
02290 
02291     /* Return function status */
02292     return HAL_ERROR;
02293   }
02294 
02295   /* HMAC Step 1 processing */
02296   if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1)
02297   {
02298     /************************** STEP 1 ******************************************/
02299     /* Configure the Number of valid bits in last word of the message */
02300     __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
02301 
02302     /* Write input buffer in Data register */
02303     hhash->Status = HASH_WriteData(hhash, hhash->pHashKeyBuffPtr, hhash->HashKeyCount);
02304     if (hhash->Status != HAL_OK)
02305     {
02306       return hhash->Status;
02307     }
02308 
02309     /* Check whether or not key entering process has been suspended */
02310     if (hhash->State == HAL_HASH_STATE_SUSPENDED)
02311     {
02312       /* Process Unlocked */
02313       __HAL_UNLOCK(hhash);
02314 
02315       /* Stop right there and return function status */
02316       return HAL_OK;
02317     }
02318 
02319     /* No processing suspension at this point: set DCAL bit. */
02320     __HAL_HASH_START_DIGEST();
02321 
02322     /* Wait for BUSY flag to be cleared */
02323     if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, Timeout) != HAL_OK)
02324     {
02325       return HAL_TIMEOUT;
02326     }
02327 
02328     /* Move from Step 1 to Step 2 */
02329     hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_2;
02330 
02331   }
02332 
02333   /* HMAC Step 2 processing.
02334      After phase check, HMAC_Processing() may
02335      - directly start up from this point in resumption case
02336        if the same Step 2 processing was suspended previously
02337     - or fall through from the Step 1 processing carried out hereabove */
02338   if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)
02339   {
02340     /************************** STEP 2 ******************************************/
02341     /* Configure the Number of valid bits in last word of the message */
02342     __HAL_HASH_SET_NBVALIDBITS(hhash->HashBuffSize);
02343 
02344     /* Write input buffer in Data register */
02345     hhash->Status = HASH_WriteData(hhash, hhash->pHashInBuffPtr, hhash->HashInCount);
02346     if (hhash->Status != HAL_OK)
02347     {
02348       return hhash->Status;
02349     }
02350 
02351     /* Check whether or not data entering process has been suspended */
02352     if (hhash->State == HAL_HASH_STATE_SUSPENDED)
02353     {
02354       /* Process Unlocked */
02355       __HAL_UNLOCK(hhash);
02356 
02357       /* Stop right there and return function status */
02358       return HAL_OK;
02359     }
02360 
02361     /* No processing suspension at this point: set DCAL bit. */
02362     __HAL_HASH_START_DIGEST();
02363 
02364     /* Wait for BUSY flag to be cleared */
02365     if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, Timeout) != HAL_OK)
02366     {
02367       return HAL_TIMEOUT;
02368     }
02369 
02370     /* Move from Step 2 to Step 3 */
02371     hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_3;
02372     /* In case Step 1 phase was suspended then resumed,
02373        set again Key input buffers and size before moving to
02374        next step */
02375     hhash->pHashKeyBuffPtr = hhash->Init.pKey;
02376     hhash->HashKeyCount    = hhash->Init.KeySize;
02377   }
02378 
02379 
02380   /* HMAC Step 3 processing.
02381       After phase check, HMAC_Processing() may
02382       - directly start up from this point in resumption case
02383         if the same Step 3 processing was suspended previously
02384      - or fall through from the Step 2 processing carried out hereabove */
02385   if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3)
02386   {
02387     /************************** STEP 3 ******************************************/
02388     /* Configure the Number of valid bits in last word of the message */
02389     __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
02390 
02391     /* Write input buffer in Data register */
02392     hhash->Status = HASH_WriteData(hhash, hhash->pHashKeyBuffPtr, hhash->HashKeyCount);
02393     if (hhash->Status != HAL_OK)
02394     {
02395       return hhash->Status;
02396     }
02397 
02398     /* Check whether or not key entering process has been suspended */
02399     if (hhash->State == HAL_HASH_STATE_SUSPENDED)
02400     {
02401       /* Process Unlocked */
02402       __HAL_UNLOCK(hhash);
02403 
02404       /* Stop right there and return function status */
02405       return HAL_OK;
02406     }
02407 
02408     /* No processing suspension at this point: start the Digest calculation. */
02409     __HAL_HASH_START_DIGEST();
02410 
02411     /* Wait for DCIS flag to be set */
02412     if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_DCIS, RESET, Timeout) != HAL_OK)
02413     {
02414       return HAL_TIMEOUT;
02415     }
02416 
02417     /* Read the message digest */
02418     HASH_GetDigest(hhash->pHashOutBuffPtr, HASH_DIGEST_LENGTH());
02419 
02420     /* Reset HASH state machine */
02421     hhash->Phase = HAL_HASH_PHASE_READY;
02422   }
02423 
02424   /* Change the HASH state */
02425   hhash->State = HAL_HASH_STATE_READY;
02426 
02427   /* Process Unlock */
02428   __HAL_UNLOCK(hhash);
02429 
02430   /* Return function status */
02431   return HAL_OK;
02432 }
02433 
02434 
02435 /**
02436   * @brief  Initialize the HASH peripheral, next process pInBuffer then
02437   *         read the computed digest.
02438   * @note   Digest is available in pOutBuffer.
02439   * @param  hhash HASH handle.
02440   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
02441   * @param  Size length of the input buffer in bytes.
02442   * @param  pOutBuffer pointer to the computed digest.
02443   * @param  Timeout Timeout value.
02444   * @param  Algorithm HASH algorithm.
02445   * @retval HAL status
02446   */
02447 HAL_StatusTypeDef HASH_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer,
02448                              uint32_t Timeout, uint32_t Algorithm)
02449 {
02450   uint8_t *pInBuffer_tmp;  /* input data address, input parameter of HASH_WriteData()         */
02451   uint32_t Size_tmp; /* input data size (in bytes), input parameter of HASH_WriteData() */
02452   HAL_HASH_StateTypeDef State_tmp = hhash->State;
02453 
02454 
02455   /* Initiate HASH processing in case of start or resumption */
02456   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
02457   {
02458     /* Check input parameters */
02459     if ((pInBuffer == NULL) || (pOutBuffer == NULL))
02460     {
02461       hhash->State = HAL_HASH_STATE_READY;
02462       return  HAL_ERROR;
02463     }
02464 
02465     /* Process Locked */
02466     __HAL_LOCK(hhash);
02467 
02468     /* Check if initialization phase has not been already performed */
02469     if (hhash->Phase == HAL_HASH_PHASE_READY)
02470     {
02471       /* Change the HASH state */
02472       hhash->State = HAL_HASH_STATE_BUSY;
02473 
02474       /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
02475       MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT);
02476 
02477       /* Configure the number of valid bits in last word of the message */
02478       __HAL_HASH_SET_NBVALIDBITS(Size);
02479 
02480       /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as
02481       input parameters of HASH_WriteData() */
02482       pInBuffer_tmp = pInBuffer;   /* pInBuffer_tmp is set to the input data address */
02483       Size_tmp = Size;             /* Size_tmp contains the input data size in bytes */
02484 
02485       /* Set the phase */
02486       hhash->Phase = HAL_HASH_PHASE_PROCESS;
02487     }
02488     else if (hhash->Phase == HAL_HASH_PHASE_PROCESS)
02489     {
02490       /* if the Peripheral has already been initialized, two cases are possible */
02491 
02492       /* Process resumption time ... */
02493       if (hhash->State == HAL_HASH_STATE_SUSPENDED)
02494       {
02495         /* Since this is resumption, pInBuffer_tmp and Size_tmp are not set
02496         to the API input parameters but to those saved beforehand by HASH_WriteData()
02497         when the processing was suspended */
02498         pInBuffer_tmp = hhash->pHashInBuffPtr;
02499         Size_tmp = hhash->HashInCount;
02500       }
02501       /* ... or multi-buffer HASH processing end */
02502       else
02503       {
02504         /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as
02505         input parameters of HASH_WriteData() */
02506         pInBuffer_tmp = pInBuffer;
02507         Size_tmp = Size;
02508         /* Configure the number of valid bits in last word of the message */
02509         __HAL_HASH_SET_NBVALIDBITS(Size);
02510       }
02511       /* Change the HASH state */
02512       hhash->State = HAL_HASH_STATE_BUSY;
02513     }
02514     else
02515     {
02516       /* Phase error */
02517       hhash->State = HAL_HASH_STATE_READY;
02518 
02519       /* Process Unlocked */
02520       __HAL_UNLOCK(hhash);
02521 
02522       /* Return function status */
02523       return HAL_ERROR;
02524     }
02525 
02526 
02527     /* Write input buffer in Data register */
02528     hhash->Status = HASH_WriteData(hhash, pInBuffer_tmp, Size_tmp);
02529     if (hhash->Status != HAL_OK)
02530     {
02531       return hhash->Status;
02532     }
02533 
02534     /* If the process has not been suspended, carry on to digest calculation */
02535     if (hhash->State != HAL_HASH_STATE_SUSPENDED)
02536     {
02537       /* Start the Digest calculation */
02538       __HAL_HASH_START_DIGEST();
02539 
02540       /* Wait for DCIS flag to be set */
02541       if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_DCIS, RESET, Timeout) != HAL_OK)
02542       {
02543         return HAL_TIMEOUT;
02544       }
02545 
02546       /* Read the message digest */
02547       HASH_GetDigest(pOutBuffer, HASH_DIGEST_LENGTH());
02548 
02549       /* Change the HASH state */
02550       hhash->State = HAL_HASH_STATE_READY;
02551 
02552       /* Reset HASH state machine */
02553       hhash->Phase = HAL_HASH_PHASE_READY;
02554 
02555     }
02556 
02557     /* Process Unlocked */
02558     __HAL_UNLOCK(hhash);
02559 
02560     /* Return function status */
02561     return HAL_OK;
02562 
02563   }
02564   else
02565   {
02566     return HAL_BUSY;
02567   }
02568 }
02569 
02570 
02571 /**
02572   * @brief  If not already done, initialize the HASH peripheral then
02573   *         processes pInBuffer.
02574   * @note   Field hhash->Phase of HASH handle is tested to check whether or not
02575   *         the Peripheral has already been initialized.
02576   * @note   The input buffer size (in bytes) must be a multiple of 4 otherwise, the
02577   *         HASH digest computation is corrupted.
02578   * @param  hhash HASH handle.
02579   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
02580   * @param  Size length of the input buffer in bytes, must be a multiple of 4.
02581   * @param  Algorithm HASH algorithm.
02582   * @retval HAL status
02583   */
02584 HAL_StatusTypeDef HASH_Accumulate(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm)
02585 {
02586   uint8_t *pInBuffer_tmp;   /* input data address, input parameter of HASH_WriteData()         */
02587   uint32_t Size_tmp;  /* input data size (in bytes), input parameter of HASH_WriteData() */
02588   HAL_HASH_StateTypeDef State_tmp = hhash->State;
02589 
02590   /* Make sure the input buffer size (in bytes) is a multiple of 4 */
02591   if ((Size % 4U) != 0U)
02592   {
02593     return  HAL_ERROR;
02594   }
02595 
02596   /* Initiate HASH processing in case of start or resumption */
02597   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
02598   {
02599     /* Check input parameters */
02600     if ((pInBuffer == NULL) || (Size == 0U))
02601     {
02602       hhash->State = HAL_HASH_STATE_READY;
02603       return  HAL_ERROR;
02604     }
02605 
02606     /* Process Locked */
02607     __HAL_LOCK(hhash);
02608 
02609     /* If resuming the HASH processing */
02610     if (hhash->State == HAL_HASH_STATE_SUSPENDED)
02611     {
02612       /* Change the HASH state */
02613       hhash->State = HAL_HASH_STATE_BUSY;
02614 
02615       /* Since this is resumption, pInBuffer_tmp and Size_tmp are not set
02616          to the API input parameters but to those saved beforehand by HASH_WriteData()
02617          when the processing was suspended */
02618       pInBuffer_tmp = hhash->pHashInBuffPtr;  /* pInBuffer_tmp is set to the input data address */
02619       Size_tmp = hhash->HashInCount;          /* Size_tmp contains the input data size in bytes */
02620 
02621     }
02622     else
02623     {
02624       /* Change the HASH state */
02625       hhash->State = HAL_HASH_STATE_BUSY;
02626 
02627       /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as
02628          input parameters of HASH_WriteData() */
02629       pInBuffer_tmp = pInBuffer;    /* pInBuffer_tmp is set to the input data address */
02630       Size_tmp = Size;              /* Size_tmp contains the input data size in bytes */
02631 
02632       /* Check if initialization phase has already be performed */
02633       if (hhash->Phase == HAL_HASH_PHASE_READY)
02634       {
02635         /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
02636         MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT);
02637       }
02638 
02639       /* Set the phase */
02640       hhash->Phase = HAL_HASH_PHASE_PROCESS;
02641 
02642     }
02643 
02644     /* Write input buffer in Data register */
02645     hhash->Status = HASH_WriteData(hhash, pInBuffer_tmp, Size_tmp);
02646     if (hhash->Status != HAL_OK)
02647     {
02648       return hhash->Status;
02649     }
02650 
02651     /* If the process has not been suspended, move the state to Ready */
02652     if (hhash->State != HAL_HASH_STATE_SUSPENDED)
02653     {
02654       /* Change the HASH state */
02655       hhash->State = HAL_HASH_STATE_READY;
02656     }
02657 
02658     /* Process Unlocked */
02659     __HAL_UNLOCK(hhash);
02660 
02661     /* Return function status */
02662     return HAL_OK;
02663 
02664   }
02665   else
02666   {
02667     return HAL_BUSY;
02668   }
02669 
02670 
02671 }
02672 
02673 
02674 /**
02675   * @brief  If not already done, initialize the HASH peripheral then
02676   *         processes pInBuffer in interruption mode.
02677   * @note   Field hhash->Phase of HASH handle is tested to check whether or not
02678   *         the Peripheral has already been initialized.
02679   * @note   The input buffer size (in bytes) must be a multiple of 4 otherwise, the
02680   *         HASH digest computation is corrupted.
02681   * @param  hhash HASH handle.
02682   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
02683   * @param  Size length of the input buffer in bytes, must be a multiple of 4.
02684   * @param  Algorithm HASH algorithm.
02685   * @retval HAL status
02686   */
02687 HAL_StatusTypeDef HASH_Accumulate_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm)
02688 {
02689   HAL_HASH_StateTypeDef State_tmp = hhash->State;
02690   __IO uint32_t inputaddr = (uint32_t) pInBuffer;
02691   uint32_t SizeVar = Size;
02692 
02693   /* Make sure the input buffer size (in bytes) is a multiple of 4 */
02694   if ((Size % 4U) != 0U)
02695   {
02696     return  HAL_ERROR;
02697   }
02698 
02699   /* Initiate HASH processing in case of start or resumption */
02700   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
02701   {
02702     /* Check input parameters */
02703     if ((pInBuffer == NULL) || (Size == 0U))
02704     {
02705       hhash->State = HAL_HASH_STATE_READY;
02706       return  HAL_ERROR;
02707     }
02708 
02709     /* Process Locked */
02710     __HAL_LOCK(hhash);
02711 
02712     /* If resuming the HASH processing */
02713     if (hhash->State == HAL_HASH_STATE_SUSPENDED)
02714     {
02715       /* Change the HASH state */
02716       hhash->State = HAL_HASH_STATE_BUSY;
02717     }
02718     else
02719     {
02720       /* Change the HASH state */
02721       hhash->State = HAL_HASH_STATE_BUSY;
02722 
02723       /* Check if initialization phase has already be performed */
02724       if (hhash->Phase == HAL_HASH_PHASE_READY)
02725       {
02726         /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
02727         MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT);
02728         hhash->HashITCounter = 1;
02729       }
02730       else
02731       {
02732         hhash->HashITCounter = 3; /* 'cruise-speed' reached during a previous buffer processing */
02733       }
02734 
02735       /* Set the phase */
02736       hhash->Phase = HAL_HASH_PHASE_PROCESS;
02737 
02738       /* If DINIS is equal to 0 (for example if an incomplete block has been previously
02739        fed to the Peripheral), the DINIE interruption won't be triggered when DINIE is set.
02740        Therefore, first words are manually entered until DINIS raises, or until there
02741        is not more data to enter. */
02742       while ((!(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))) && (SizeVar > 0U))
02743       {
02744 
02745         /* Write input data 4 bytes at a time */
02746         HASH->DIN = *(uint32_t *)inputaddr;
02747         inputaddr += 4U;
02748         SizeVar -= 4U;
02749       }
02750 
02751       /* If DINIS is still not set or if all the data have been fed, stop here */
02752       if ((!(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))) || (SizeVar == 0U))
02753       {
02754         /* Change the HASH state */
02755         hhash->State = HAL_HASH_STATE_READY;
02756 
02757         /* Process Unlock */
02758         __HAL_UNLOCK(hhash);
02759 
02760         /* Return function status */
02761         return HAL_OK;
02762       }
02763 
02764       /* otherwise, carry on in interrupt-mode */
02765       hhash->HashInCount = SizeVar;               /* Counter used to keep track of number of data
02766                                                   to be fed to the Peripheral */
02767       hhash->pHashInBuffPtr = (uint8_t *)inputaddr;       /* Points at data which will be fed to the Peripheral at
02768                                                   the next interruption */
02769       /* In case of suspension, hhash->HashInCount and hhash->pHashInBuffPtr contain
02770          the information describing where the HASH process is stopped.
02771          These variables are used later on to resume the HASH processing at the
02772          correct location. */
02773 
02774     }
02775 
02776     /* Set multi buffers accumulation flag */
02777     hhash->Accumulation = 1U;
02778 
02779     /* Process Unlock */
02780     __HAL_UNLOCK(hhash);
02781 
02782     /* Enable Data Input interrupt */
02783     __HAL_HASH_ENABLE_IT(HASH_IT_DINI);
02784 
02785     /* Return function status */
02786     return HAL_OK;
02787 
02788   }
02789   else
02790   {
02791     return HAL_BUSY;
02792   }
02793 
02794 }
02795 
02796 
02797 
02798 /**
02799   * @brief  Initialize the HASH peripheral, next process pInBuffer then
02800   *         read the computed digest in interruption mode.
02801   * @note   Digest is available in pOutBuffer.
02802   * @param  hhash HASH handle.
02803   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
02804   * @param  Size length of the input buffer in bytes.
02805   * @param  pOutBuffer pointer to the computed digest.
02806   * @param  Algorithm HASH algorithm.
02807   * @retval HAL status
02808   */
02809 HAL_StatusTypeDef HASH_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer,
02810                                 uint32_t Algorithm)
02811 {
02812   HAL_HASH_StateTypeDef State_tmp = hhash->State;
02813   __IO uint32_t inputaddr = (uint32_t) pInBuffer;
02814   uint32_t polling_step = 0U;
02815   uint32_t initialization_skipped = 0U;
02816   uint32_t SizeVar = Size;
02817 
02818   /* If State is ready or suspended, start or resume IT-based HASH processing */
02819   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
02820   {
02821     /* Check input parameters */
02822     if ((pInBuffer == NULL) || (Size == 0U) || (pOutBuffer == NULL))
02823     {
02824       hhash->State = HAL_HASH_STATE_READY;
02825       return  HAL_ERROR;
02826     }
02827 
02828     /* Process Locked */
02829     __HAL_LOCK(hhash);
02830 
02831     /* Change the HASH state */
02832     hhash->State = HAL_HASH_STATE_BUSY;
02833 
02834     /* Initialize IT counter */
02835     hhash->HashITCounter = 1;
02836 
02837     /* Check if initialization phase has already be performed */
02838     if (hhash->Phase == HAL_HASH_PHASE_READY)
02839     {
02840       /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
02841       MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT);
02842 
02843       /* Configure the number of valid bits in last word of the message */
02844       __HAL_HASH_SET_NBVALIDBITS(SizeVar);
02845 
02846 
02847       hhash->HashInCount = SizeVar;            /* Counter used to keep track of number of data
02848                                                   to be fed to the Peripheral */
02849       hhash->pHashInBuffPtr = pInBuffer;       /* Points at data which will be fed to the Peripheral at
02850                                                   the next interruption */
02851       /* In case of suspension, hhash->HashInCount and hhash->pHashInBuffPtr contain
02852          the information describing where the HASH process is stopped.
02853          These variables are used later on to resume the HASH processing at the
02854          correct location. */
02855 
02856       hhash->pHashOutBuffPtr = pOutBuffer;     /* Points at the computed digest */
02857     }
02858     else
02859     {
02860       initialization_skipped = 1; /* info user later on in case of multi-buffer */
02861     }
02862 
02863     /* Set the phase */
02864     hhash->Phase = HAL_HASH_PHASE_PROCESS;
02865 
02866     /* If DINIS is equal to 0 (for example if an incomplete block has been previously
02867       fed to the Peripheral), the DINIE interruption won't be triggered when DINIE is set.
02868       Therefore, first words are manually entered until DINIS raises. */
02869     while ((!(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))) && (SizeVar > 3U))
02870     {
02871       polling_step = 1U; /* note that some words are entered before enabling the interrupt */
02872 
02873       /* Write input data 4 bytes at a time */
02874       HASH->DIN = *(uint32_t *)inputaddr;
02875       inputaddr += 4U;
02876       SizeVar -= 4U;
02877     }
02878 
02879     if (polling_step == 1U)
02880     {
02881       if (SizeVar == 0U)
02882       {
02883         /* If all the data have been entered at this point, it only remains to
02884          read the digest */
02885         hhash->pHashOutBuffPtr = pOutBuffer;     /* Points at the computed digest */
02886 
02887         /* Start the Digest calculation */
02888         __HAL_HASH_START_DIGEST();
02889         /* Process Unlock */
02890         __HAL_UNLOCK(hhash);
02891 
02892         /* Enable Interrupts */
02893         __HAL_HASH_ENABLE_IT(HASH_IT_DCI);
02894 
02895         /* Return function status */
02896         return HAL_OK;
02897       }
02898       else if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))
02899       {
02900         /* It remains data to enter and the Peripheral is ready to trigger DINIE,
02901            carry on as usual.
02902            Update HashInCount and pHashInBuffPtr accordingly. */
02903         hhash->HashInCount = SizeVar;
02904         hhash->pHashInBuffPtr = (uint8_t *)inputaddr;
02905         /* Update the configuration of the number of valid bits in last word of the message */
02906         __HAL_HASH_SET_NBVALIDBITS(SizeVar);
02907         hhash->pHashOutBuffPtr = pOutBuffer;  /* Points at the computed digest */
02908         if (initialization_skipped == 1U)
02909         {
02910           hhash->HashITCounter = 3; /* 'cruise-speed' reached during a previous buffer processing */
02911         }
02912       }
02913       else
02914       {
02915         /* DINIS is not set but it remains a few data to enter (not enough for a full word).
02916            Manually enter the last bytes before enabling DCIE. */
02917         __HAL_HASH_SET_NBVALIDBITS(SizeVar);
02918         HASH->DIN = *(uint32_t *)inputaddr;
02919 
02920         /* Start the Digest calculation */
02921         hhash->pHashOutBuffPtr = pOutBuffer;     /* Points at the computed digest */
02922         __HAL_HASH_START_DIGEST();
02923         /* Process Unlock */
02924         __HAL_UNLOCK(hhash);
02925 
02926         /* Enable Interrupts */
02927         __HAL_HASH_ENABLE_IT(HASH_IT_DCI);
02928 
02929         /* Return function status */
02930         return HAL_OK;
02931       }
02932     } /*  if (polling_step == 1) */
02933 
02934 
02935     /* Process Unlock */
02936     __HAL_UNLOCK(hhash);
02937 
02938     /* Enable Interrupts */
02939     __HAL_HASH_ENABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
02940 
02941     /* Return function status */
02942     return HAL_OK;
02943   }
02944   else
02945   {
02946     return HAL_BUSY;
02947   }
02948 
02949 }
02950 
02951 
02952 /**
02953   * @brief  Initialize the HASH peripheral then initiate a DMA transfer
02954   *         to feed the input buffer to the Peripheral.
02955   * @note   If MDMAT bit is set before calling this function (multi-buffer
02956   *          HASH processing case), the input buffer size (in bytes) must be
02957   *          a multiple of 4 otherwise, the HASH digest computation is corrupted.
02958   *          For the processing of the last buffer of the thread, MDMAT bit must
02959   *          be reset and the buffer length (in bytes) doesn't have to be a
02960   *          multiple of 4.
02961   * @param  hhash HASH handle.
02962   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
02963   * @param  Size length of the input buffer in bytes.
02964   * @param  Algorithm HASH algorithm.
02965   * @retval HAL status
02966   */
02967 HAL_StatusTypeDef HASH_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm)
02968 {
02969   uint32_t inputaddr;
02970   uint32_t inputSize;
02971   HAL_StatusTypeDef status ;
02972   HAL_HASH_StateTypeDef State_tmp = hhash->State;
02973 
02974 
02975   /* Make sure the input buffer size (in bytes) is a multiple of 4 when MDMAT bit is set
02976      (case of multi-buffer HASH processing) */
02977   assert_param(IS_HASH_DMA_MULTIBUFFER_SIZE(Size));
02978 
02979   /* If State is ready or suspended, start or resume polling-based HASH processing */
02980   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
02981   {
02982     /* Check input parameters */
02983     if ((pInBuffer == NULL) || (Size == 0U) ||
02984         /* Check phase coherency. Phase must be
02985            either READY (fresh start)
02986            or PROCESS (multi-buffer HASH management) */
02987         ((hhash->Phase != HAL_HASH_PHASE_READY) && (!(IS_HASH_PROCESSING(hhash)))))
02988     {
02989       hhash->State = HAL_HASH_STATE_READY;
02990       return  HAL_ERROR;
02991     }
02992 
02993 
02994     /* Process Locked */
02995     __HAL_LOCK(hhash);
02996 
02997     /* If not a resumption case */
02998     if (hhash->State == HAL_HASH_STATE_READY)
02999     {
03000       /* Change the HASH state */
03001       hhash->State = HAL_HASH_STATE_BUSY;
03002 
03003       /* Check if initialization phase has already been performed.
03004          If Phase is already set to HAL_HASH_PHASE_PROCESS, this means the
03005          API is processing a new input data message in case of multi-buffer HASH
03006          computation. */
03007       if (hhash->Phase == HAL_HASH_PHASE_READY)
03008       {
03009         /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
03010         MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT);
03011 
03012         /* Set the phase */
03013         hhash->Phase = HAL_HASH_PHASE_PROCESS;
03014       }
03015 
03016       /* Configure the Number of valid bits in last word of the message */
03017       __HAL_HASH_SET_NBVALIDBITS(Size);
03018 
03019       inputaddr = (uint32_t)pInBuffer;     /* DMA transfer start address   */
03020       inputSize = Size;                    /* DMA transfer size (in bytes) */
03021 
03022       /* In case of suspension request, save the starting parameters */
03023       hhash->pHashInBuffPtr =  pInBuffer;  /* DMA transfer start address   */
03024       hhash->HashInCount = Size;           /* DMA transfer size (in bytes) */
03025 
03026     }
03027     /* If resumption case */
03028     else
03029     {
03030       /* Change the HASH state */
03031       hhash->State = HAL_HASH_STATE_BUSY;
03032 
03033       /* Resumption case, inputaddr and inputSize are not set to the API input parameters
03034          but to those saved beforehand by HAL_HASH_DMAFeed_ProcessSuspend() when the
03035          processing was suspended */
03036       inputaddr = (uint32_t)hhash->pHashInBuffPtr;  /* DMA transfer start address   */
03037       inputSize = hhash->HashInCount;               /* DMA transfer size (in bytes) */
03038 
03039     }
03040 
03041     /* Set the HASH DMA transfer complete callback */
03042     hhash->hdmain->XferCpltCallback = HASH_DMAXferCplt;
03043     /* Set the DMA error callback */
03044     hhash->hdmain->XferErrorCallback = HASH_DMAError;
03045 
03046     /* Store number of words already pushed to manage proper DMA processing suspension */
03047     hhash->NbWordsAlreadyPushed = HASH_NBW_PUSHED();
03048 
03049     /* Enable the DMA In DMA stream */
03050     status = HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, \
03051                               (((inputSize % 4U) != 0U) ? ((inputSize + (4U - (inputSize % 4U))) / 4U) : \
03052                                (inputSize / 4U)));
03053 
03054     /* Enable DMA requests */
03055     SET_BIT(HASH->CR, HASH_CR_DMAE);
03056 
03057     /* Process Unlock */
03058     __HAL_UNLOCK(hhash);
03059 
03060     /* Return function status */
03061     if (status != HAL_OK)
03062     {
03063       /* Update HASH state machine to error */
03064       hhash->State = HAL_HASH_STATE_ERROR;
03065     }
03066 
03067     return status;
03068   }
03069   else
03070   {
03071     return HAL_BUSY;
03072   }
03073 }
03074 
03075 /**
03076   * @brief  Return the computed digest.
03077   * @note   The API waits for DCIS to be set then reads the computed digest.
03078   * @param  hhash HASH handle.
03079   * @param  pOutBuffer pointer to the computed digest.
03080   * @param  Timeout Timeout value.
03081   * @retval HAL status
03082   */
03083 HAL_StatusTypeDef HASH_Finish(HASH_HandleTypeDef *hhash, uint8_t *pOutBuffer, uint32_t Timeout)
03084 {
03085 
03086   if (hhash->State == HAL_HASH_STATE_READY)
03087   {
03088     /* Check parameter */
03089     if (pOutBuffer == NULL)
03090     {
03091       return  HAL_ERROR;
03092     }
03093 
03094     /* Process Locked */
03095     __HAL_LOCK(hhash);
03096 
03097     /* Change the HASH state to busy */
03098     hhash->State = HAL_HASH_STATE_BUSY;
03099 
03100     /* Wait for DCIS flag to be set */
03101     if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_DCIS, RESET, Timeout) != HAL_OK)
03102     {
03103       return HAL_TIMEOUT;
03104     }
03105 
03106     /* Read the message digest */
03107     HASH_GetDigest(pOutBuffer, HASH_DIGEST_LENGTH());
03108 
03109     /* Change the HASH state to ready */
03110     hhash->State = HAL_HASH_STATE_READY;
03111 
03112     /* Reset HASH state machine */
03113     hhash->Phase = HAL_HASH_PHASE_READY;
03114 
03115     /* Process UnLock */
03116     __HAL_UNLOCK(hhash);
03117 
03118     /* Return function status */
03119     return HAL_OK;
03120 
03121   }
03122   else
03123   {
03124     return HAL_BUSY;
03125   }
03126 
03127 }
03128 
03129 
03130 /**
03131   * @brief  Initialize the HASH peripheral in HMAC mode, next process pInBuffer then
03132   *         read the computed digest.
03133   * @note   Digest is available in pOutBuffer.
03134   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
03135   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
03136   * @param  hhash HASH handle.
03137   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
03138   * @param  Size length of the input buffer in bytes.
03139   * @param  pOutBuffer pointer to the computed digest.
03140   * @param  Timeout Timeout value.
03141   * @param  Algorithm HASH algorithm.
03142   * @retval HAL status
03143   */
03144 HAL_StatusTypeDef HMAC_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer,
03145                              uint32_t Timeout, uint32_t Algorithm)
03146 {
03147   HAL_HASH_StateTypeDef State_tmp = hhash->State;
03148 
03149   /* If State is ready or suspended, start or resume polling-based HASH processing */
03150   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
03151   {
03152     /* Check input parameters */
03153     if ((pInBuffer == NULL) || (Size == 0U) || (hhash->Init.pKey == NULL) || (hhash->Init.KeySize == 0U)
03154         || (pOutBuffer == NULL))
03155     {
03156       hhash->State = HAL_HASH_STATE_READY;
03157       return  HAL_ERROR;
03158     }
03159 
03160     /* Process Locked */
03161     __HAL_LOCK(hhash);
03162 
03163     /* Change the HASH state */
03164     hhash->State = HAL_HASH_STATE_BUSY;
03165 
03166     /* Check if initialization phase has already be performed */
03167     if (hhash->Phase == HAL_HASH_PHASE_READY)
03168     {
03169       /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits */
03170       if (hhash->Init.KeySize > 64U)
03171       {
03172         MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
03173                    Algorithm | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT);
03174       }
03175       else
03176       {
03177         MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
03178                    Algorithm | HASH_ALGOMODE_HMAC | HASH_CR_INIT);
03179       }
03180       /* Set the phase to Step 1 */
03181       hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_1;
03182       /* Resort to hhash internal fields to feed the Peripheral.
03183          Parameters will be updated in case of suspension to contain the proper
03184          information at resumption time. */
03185       hhash->pHashOutBuffPtr  = pOutBuffer;            /* Output digest address    */
03186       hhash->pHashInBuffPtr   = pInBuffer;             /* Input data address, HMAC_Processing input
03187                                                           parameter for Step 2     */
03188       hhash->HashInCount      = Size;                  /* Input data size, HMAC_Processing input
03189                                                           parameter for Step 2        */
03190       hhash->HashBuffSize     = Size;                  /* Store the input buffer size for the whole HMAC process*/
03191       hhash->pHashKeyBuffPtr  = hhash->Init.pKey;      /* Key address, HMAC_Processing input parameter for Step
03192                                                           1 and Step 3 */
03193       hhash->HashKeyCount     = hhash->Init.KeySize;   /* Key size, HMAC_Processing input parameter for Step 1
03194                                                           and Step 3    */
03195     }
03196 
03197     /* Carry out HMAC processing */
03198     return HMAC_Processing(hhash, Timeout);
03199 
03200   }
03201   else
03202   {
03203     return HAL_BUSY;
03204   }
03205 }
03206 
03207 
03208 
03209 /**
03210   * @brief  Initialize the HASH peripheral in HMAC mode, next process pInBuffer then
03211   *         read the computed digest in interruption mode.
03212   * @note   Digest is available in pOutBuffer.
03213   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
03214   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
03215   * @param  hhash HASH handle.
03216   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
03217   * @param  Size length of the input buffer in bytes.
03218   * @param  pOutBuffer pointer to the computed digest.
03219   * @param  Algorithm HASH algorithm.
03220   * @retval HAL status
03221   */
03222 HAL_StatusTypeDef HMAC_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer,
03223                                 uint32_t Algorithm)
03224 {
03225   HAL_HASH_StateTypeDef State_tmp = hhash->State;
03226 
03227   /* If State is ready or suspended, start or resume IT-based HASH processing */
03228   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
03229   {
03230     /* Check input parameters */
03231     if ((pInBuffer == NULL) || (Size == 0U) || (hhash->Init.pKey == NULL) || (hhash->Init.KeySize == 0U)
03232         || (pOutBuffer == NULL))
03233     {
03234       hhash->State = HAL_HASH_STATE_READY;
03235       return  HAL_ERROR;
03236     }
03237 
03238     /* Process Locked */
03239     __HAL_LOCK(hhash);
03240 
03241     /* Change the HASH state */
03242     hhash->State = HAL_HASH_STATE_BUSY;
03243 
03244     /* Initialize IT counter */
03245     hhash->HashITCounter = 1;
03246 
03247     /* Check if initialization phase has already be performed */
03248     if (hhash->Phase == HAL_HASH_PHASE_READY)
03249     {
03250       /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits */
03251       if (hhash->Init.KeySize > 64U)
03252       {
03253         MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
03254                    Algorithm | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT);
03255       }
03256       else
03257       {
03258         MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
03259                    Algorithm | HASH_ALGOMODE_HMAC | HASH_CR_INIT);
03260       }
03261 
03262       /* Resort to hhash internal fields hhash->pHashInBuffPtr and hhash->HashInCount
03263          to feed the Peripheral whatever the HMAC step.
03264          Lines below are set to start HMAC Step 1 processing where key is entered first. */
03265       hhash->HashInCount     = hhash->Init.KeySize; /* Key size                      */
03266       hhash->pHashInBuffPtr  = hhash->Init.pKey ;   /* Key address                   */
03267 
03268       /* Store input and output parameters in handle fields to manage steps transition
03269          or possible HMAC suspension/resumption */
03270       hhash->pHashKeyBuffPtr = hhash->Init.pKey;    /* Key address                   */
03271       hhash->pHashMsgBuffPtr = pInBuffer;           /* Input message address         */
03272       hhash->HashBuffSize    = Size;                /* Input message size (in bytes) */
03273       hhash->pHashOutBuffPtr = pOutBuffer;          /* Output digest address         */
03274 
03275       /* Configure the number of valid bits in last word of the key */
03276       __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
03277 
03278       /* Set the phase to Step 1 */
03279       hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_1;
03280     }
03281     else if ((hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1) || (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3))
03282     {
03283       /* Restart IT-based HASH processing after Step 1 or Step 3 suspension */
03284 
03285     }
03286     else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)
03287     {
03288       /* Restart IT-based HASH processing after Step 2 suspension */
03289 
03290     }
03291     else
03292     {
03293       /* Error report as phase incorrect */
03294       /* Process Unlock */
03295       __HAL_UNLOCK(hhash);
03296       hhash->State = HAL_HASH_STATE_READY;
03297       return HAL_ERROR;
03298     }
03299 
03300     /* Process Unlock */
03301     __HAL_UNLOCK(hhash);
03302 
03303     /* Enable Interrupts */
03304     __HAL_HASH_ENABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
03305 
03306     /* Return function status */
03307     return HAL_OK;
03308   }
03309   else
03310   {
03311     return HAL_BUSY;
03312   }
03313 
03314 }
03315 
03316 
03317 
03318 /**
03319   * @brief  Initialize the HASH peripheral in HMAC mode then initiate the required
03320   *         DMA transfers to feed the key and the input buffer to the Peripheral.
03321   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
03322   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
03323   * @note   In case of multi-buffer HMAC processing, the input buffer size (in bytes) must
03324   *         be a multiple of 4 otherwise, the HASH digest computation is corrupted.
03325   *         Only the length of the last buffer of the thread doesn't have to be a
03326   *         multiple of 4.
03327   * @param  hhash HASH handle.
03328   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
03329   * @param  Size length of the input buffer in bytes.
03330   * @param  Algorithm HASH algorithm.
03331   * @retval HAL status
03332   */
03333 HAL_StatusTypeDef HMAC_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm)
03334 {
03335   uint32_t inputaddr;
03336   uint32_t inputSize;
03337   HAL_StatusTypeDef status ;
03338   HAL_HASH_StateTypeDef State_tmp = hhash->State;
03339   /* Make sure the input buffer size (in bytes) is a multiple of 4 when digest calculation
03340      is disabled (multi-buffer HMAC processing, MDMAT bit to be set) */
03341   assert_param(IS_HMAC_DMA_MULTIBUFFER_SIZE(hhash, Size));
03342   /* If State is ready or suspended, start or resume DMA-based HASH processing */
03343   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
03344   {
03345     /* Check input parameters */
03346     if ((pInBuffer == NULL) || (Size == 0U) || (hhash->Init.pKey == NULL) || (hhash->Init.KeySize == 0U) ||
03347         /* Check phase coherency. Phase must be
03348             either READY (fresh start)
03349             or one of HMAC PROCESS steps (multi-buffer HASH management) */
03350         ((hhash->Phase != HAL_HASH_PHASE_READY) && (!(IS_HMAC_PROCESSING(hhash)))))
03351     {
03352       hhash->State = HAL_HASH_STATE_READY;
03353       return  HAL_ERROR;
03354     }
03355 
03356 
03357     /* Process Locked */
03358     __HAL_LOCK(hhash);
03359 
03360     /* If not a case of resumption after suspension */
03361     if (hhash->State == HAL_HASH_STATE_READY)
03362     {
03363       /* Check whether or not initialization phase has already be performed */
03364       if (hhash->Phase == HAL_HASH_PHASE_READY)
03365       {
03366         /* Change the HASH state */
03367         hhash->State = HAL_HASH_STATE_BUSY;
03368         /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits.
03369            At the same time, ensure MDMAT bit is cleared. */
03370         if (hhash->Init.KeySize > 64U)
03371         {
03372           MODIFY_REG(HASH->CR, HASH_CR_MDMAT | HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
03373                      Algorithm | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT);
03374         }
03375         else
03376         {
03377           MODIFY_REG(HASH->CR, HASH_CR_MDMAT | HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
03378                      Algorithm | HASH_ALGOMODE_HMAC | HASH_CR_INIT);
03379         }
03380         /* Store input aparameters in handle fields to manage steps transition
03381            or possible HMAC suspension/resumption */
03382         hhash->HashInCount = hhash->Init.KeySize;   /* Initial size for first DMA transfer (key size)      */
03383         hhash->pHashKeyBuffPtr = hhash->Init.pKey;  /* Key address                                         */
03384         hhash->pHashInBuffPtr  = hhash->Init.pKey ; /* First address passed to DMA (key address at Step 1) */
03385         hhash->pHashMsgBuffPtr = pInBuffer;         /* Input data address                                  */
03386         hhash->HashBuffSize = Size;                 /* input data size (in bytes)                          */
03387 
03388         /* Set DMA input parameters */
03389         inputaddr = (uint32_t)(hhash->Init.pKey);   /* Address passed to DMA (start by entering Key message) */
03390         inputSize = hhash->Init.KeySize;            /* Size for first DMA transfer (in bytes) */
03391 
03392         /* Configure the number of valid bits in last word of the key */
03393         __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
03394 
03395         /* Set the phase to Step 1 */
03396         hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_1;
03397 
03398       }
03399       else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)
03400       {
03401         /* Process a new input data message in case of multi-buffer HMAC processing
03402           (this is not a resumption case) */
03403 
03404         /* Change the HASH state */
03405         hhash->State = HAL_HASH_STATE_BUSY;
03406 
03407         /* Save input parameters to be able to manage possible suspension/resumption */
03408         hhash->HashInCount = Size;                /* Input message address       */
03409         hhash->pHashInBuffPtr = pInBuffer;        /* Input message size in bytes */
03410 
03411         /* Set DMA input parameters */
03412         inputaddr = (uint32_t)pInBuffer;           /* Input message address       */
03413         inputSize = Size;                          /* Input message size in bytes */
03414 
03415         if (hhash->DigestCalculationDisable == RESET)
03416         {
03417           /* This means this is the last buffer of the multi-buffer sequence: DCAL needs to be set. */
03418           __HAL_HASH_RESET_MDMAT();
03419           __HAL_HASH_SET_NBVALIDBITS(inputSize);
03420         }
03421       }
03422       else
03423       {
03424         /* Phase not aligned with handle READY state */
03425         __HAL_UNLOCK(hhash);
03426         /* Return function status */
03427         return HAL_ERROR;
03428       }
03429     }
03430     else
03431     {
03432       /* Resumption case (phase may be Step 1, 2 or 3) */
03433 
03434       /* Change the HASH state */
03435       hhash->State = HAL_HASH_STATE_BUSY;
03436 
03437       /* Set DMA input parameters at resumption location;
03438          inputaddr and inputSize are not set to the API input parameters
03439          but to those saved beforehand by HAL_HASH_DMAFeed_ProcessSuspend() when the
03440          processing was suspended. */
03441       inputaddr = (uint32_t)(hhash->pHashInBuffPtr);  /* Input message address       */
03442       inputSize = hhash->HashInCount;                 /* Input message size in bytes */
03443     }
03444 
03445 
03446     /* Set the HASH DMA transfer complete callback */
03447     hhash->hdmain->XferCpltCallback = HASH_DMAXferCplt;
03448     /* Set the DMA error callback */
03449     hhash->hdmain->XferErrorCallback = HASH_DMAError;
03450 
03451     /* Store number of words already pushed to manage proper DMA processing suspension */
03452     hhash->NbWordsAlreadyPushed = HASH_NBW_PUSHED();
03453 
03454     /* Enable the DMA In DMA stream */
03455     status = HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN,  \
03456                               (((inputSize % 4U) != 0U) ? ((inputSize + (4U - (inputSize % 4U))) / 4U) \
03457                               : (inputSize / 4U)));
03458 
03459     /* Enable DMA requests */
03460     SET_BIT(HASH->CR, HASH_CR_DMAE);
03461 
03462     /* Process Unlocked */
03463     __HAL_UNLOCK(hhash);
03464 
03465     /* Return function status */
03466     if (status != HAL_OK)
03467     {
03468       /* Update HASH state machine to error */
03469       hhash->State = HAL_HASH_STATE_ERROR;
03470     }
03471 
03472     /* Return function status */
03473     return status;
03474   }
03475   else
03476   {
03477     return HAL_BUSY;
03478   }
03479 }
03480 /**
03481   * @}
03482   */
03483 
03484 #endif /* HAL_HASH_MODULE_ENABLED */
03485 
03486 /**
03487   * @}
03488   */
03489 #endif /*  HASH*/
03490 /**
03491   * @}
03492   */
03493