STM32L443xx HAL User Manual
stm32l4xx_hal_hash.c
Go to the documentation of this file.
00001 /**
00002   ******************************************************************************
00003   * @file    stm32l4xx_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 channel to manage data transfer from
00043                 memory to peripheral (input channel). 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 channel: 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 "stm32l4xx_hal.h"
00210 
00211 
00212 /** @addtogroup STM32L4xx_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_Channel_TypeDef *)hhash->hdmain->Instance)->CNDTR;
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_Channel_TypeDef *)hhash->hdmain->Instance)->CNDTR;
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 channel */
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 DINIS = 1, which occurs when 16 32-bit locations are free
01840       in the input buffer */
01841       if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))
01842       {
01843         /* Reset SuspendRequest */
01844         hhash->SuspendRequest = HAL_HASH_SUSPEND_NONE;
01845 
01846         /* Depending whether the key or the input data were fed to the Peripheral, the feeding point
01847         reached at suspension time is not saved in the same handle fields */
01848         if ((hhash->Phase == HAL_HASH_PHASE_PROCESS) || (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2))
01849         {
01850           /* Save current reading and writing locations of Input and Output buffers */
01851           hhash->pHashInBuffPtr = (uint8_t *)inputaddr;
01852           /* Save the number of bytes that remain to be processed at this point */
01853           hhash->HashInCount    =  Size - (buffercounter + 4U);
01854         }
01855         else if ((hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1) || (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3))
01856         {
01857           /* Save current reading and writing locations of Input and Output buffers */
01858           hhash->pHashKeyBuffPtr  = (uint8_t *)inputaddr;
01859           /* Save the number of bytes that remain to be processed at this point */
01860           hhash->HashKeyCount  =  Size - (buffercounter + 4U);
01861         }
01862         else
01863         {
01864           /* Unexpected phase: unlock process and report error */
01865           hhash->State = HAL_HASH_STATE_READY;
01866           __HAL_UNLOCK(hhash);
01867           return HAL_ERROR;
01868         }
01869 
01870         /* Set the HASH state to Suspended and exit to stop entering data */
01871         hhash->State = HAL_HASH_STATE_SUSPENDED;
01872 
01873         return HAL_OK;
01874       } /* if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))  */
01875     } /* if ((hhash->SuspendRequest == HAL_HASH_SUSPEND) && ((buffercounter+4) < Size)) */
01876   }   /* for(buffercounter = 0; buffercounter < Size; buffercounter+=4)                 */
01877 
01878   /* At this point, all the data have been entered to the Peripheral: exit */
01879   return  HAL_OK;
01880 }
01881 
01882 /**
01883   * @brief  Retrieve the message digest.
01884   * @param  pMsgDigest pointer to the computed digest.
01885   * @param  Size message digest size in bytes.
01886   * @retval None
01887   */
01888 static void HASH_GetDigest(uint8_t *pMsgDigest, uint8_t Size)
01889 {
01890   uint32_t msgdigest = (uint32_t)pMsgDigest;
01891 
01892   switch (Size)
01893   {
01894     /* Read the message digest */
01895     case 16:  /* MD5 */
01896       *(uint32_t *)(msgdigest) = __REV(HASH->HR[0]);
01897       msgdigest += 4U;
01898       *(uint32_t *)(msgdigest) = __REV(HASH->HR[1]);
01899       msgdigest += 4U;
01900       *(uint32_t *)(msgdigest) = __REV(HASH->HR[2]);
01901       msgdigest += 4U;
01902       *(uint32_t *)(msgdigest) = __REV(HASH->HR[3]);
01903       break;
01904     case 20:  /* SHA1 */
01905       *(uint32_t *)(msgdigest) = __REV(HASH->HR[0]);
01906       msgdigest += 4U;
01907       *(uint32_t *)(msgdigest) = __REV(HASH->HR[1]);
01908       msgdigest += 4U;
01909       *(uint32_t *)(msgdigest) = __REV(HASH->HR[2]);
01910       msgdigest += 4U;
01911       *(uint32_t *)(msgdigest) = __REV(HASH->HR[3]);
01912       msgdigest += 4U;
01913       *(uint32_t *)(msgdigest) = __REV(HASH->HR[4]);
01914       break;
01915     case 28:  /* SHA224 */
01916       *(uint32_t *)(msgdigest) = __REV(HASH->HR[0]);
01917       msgdigest += 4U;
01918       *(uint32_t *)(msgdigest) = __REV(HASH->HR[1]);
01919       msgdigest += 4U;
01920       *(uint32_t *)(msgdigest) = __REV(HASH->HR[2]);
01921       msgdigest += 4U;
01922       *(uint32_t *)(msgdigest) = __REV(HASH->HR[3]);
01923       msgdigest += 4U;
01924       *(uint32_t *)(msgdigest) = __REV(HASH->HR[4]);
01925       msgdigest += 4U;
01926       *(uint32_t *)(msgdigest) = __REV(HASH_DIGEST->HR[5]);
01927       msgdigest += 4U;
01928       *(uint32_t *)(msgdigest) = __REV(HASH_DIGEST->HR[6]);
01929       break;
01930     case 32:   /* SHA256 */
01931       *(uint32_t *)(msgdigest) = __REV(HASH->HR[0]);
01932       msgdigest += 4U;
01933       *(uint32_t *)(msgdigest) = __REV(HASH->HR[1]);
01934       msgdigest += 4U;
01935       *(uint32_t *)(msgdigest) = __REV(HASH->HR[2]);
01936       msgdigest += 4U;
01937       *(uint32_t *)(msgdigest) = __REV(HASH->HR[3]);
01938       msgdigest += 4U;
01939       *(uint32_t *)(msgdigest) = __REV(HASH->HR[4]);
01940       msgdigest += 4U;
01941       *(uint32_t *)(msgdigest) = __REV(HASH_DIGEST->HR[5]);
01942       msgdigest += 4U;
01943       *(uint32_t *)(msgdigest) = __REV(HASH_DIGEST->HR[6]);
01944       msgdigest += 4U;
01945       *(uint32_t *)(msgdigest) = __REV(HASH_DIGEST->HR[7]);
01946       break;
01947     default:
01948       break;
01949   }
01950 }
01951 
01952 
01953 
01954 /**
01955   * @brief  Handle HASH processing Timeout.
01956   * @param  hhash HASH handle.
01957   * @param  Flag specifies the HASH flag to check.
01958   * @param  Status the Flag status (SET or RESET).
01959   * @param  Timeout Timeout duration.
01960   * @retval HAL status
01961   */
01962 static HAL_StatusTypeDef HASH_WaitOnFlagUntilTimeout(HASH_HandleTypeDef *hhash, uint32_t Flag, FlagStatus Status,
01963                                                      uint32_t Timeout)
01964 {
01965   uint32_t tickstart = HAL_GetTick();
01966 
01967   /* Wait until flag is set */
01968   if (Status == RESET)
01969   {
01970     while (__HAL_HASH_GET_FLAG(Flag) == RESET)
01971     {
01972       /* Check for the Timeout */
01973       if (Timeout != HAL_MAX_DELAY)
01974       {
01975         if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
01976         {
01977           /* Set State to Ready to be able to restart later on */
01978           hhash->State  = HAL_HASH_STATE_READY;
01979           /* Store time out issue in handle status */
01980           hhash->Status = HAL_TIMEOUT;
01981 
01982           /* Process Unlocked */
01983           __HAL_UNLOCK(hhash);
01984 
01985           return HAL_TIMEOUT;
01986         }
01987       }
01988     }
01989   }
01990   else
01991   {
01992     while (__HAL_HASH_GET_FLAG(Flag) != RESET)
01993     {
01994       /* Check for the Timeout */
01995       if (Timeout != HAL_MAX_DELAY)
01996       {
01997         if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
01998         {
01999           /* Set State to Ready to be able to restart later on */
02000           hhash->State  = HAL_HASH_STATE_READY;
02001           /* Store time out issue in handle status */
02002           hhash->Status = HAL_TIMEOUT;
02003 
02004           /* Process Unlocked */
02005           __HAL_UNLOCK(hhash);
02006 
02007           return HAL_TIMEOUT;
02008         }
02009       }
02010     }
02011   }
02012   return HAL_OK;
02013 }
02014 
02015 
02016 /**
02017   * @brief  HASH processing in interruption mode.
02018   * @param  hhash HASH handle.
02019   * @note   HASH_IT() regularly reads hhash->SuspendRequest to check whether
02020   *         or not the HASH processing must be suspended. If this is the case, the
02021   *         processing is suspended when possible and the Peripheral feeding point reached at
02022   *         suspension time is stored in the handle for resumption later on.
02023   * @retval HAL status
02024   */
02025 static HAL_StatusTypeDef HASH_IT(HASH_HandleTypeDef *hhash)
02026 {
02027   if (hhash->State == HAL_HASH_STATE_BUSY)
02028   {
02029     /* ITCounter must not be equal to 0 at this point. Report an error if this is the case. */
02030     if (hhash->HashITCounter == 0U)
02031     {
02032       /* Disable Interrupts */
02033       __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
02034       /* HASH state set back to Ready to prevent any issue in user code
02035          present in HAL_HASH_ErrorCallback() */
02036       hhash->State = HAL_HASH_STATE_READY;
02037       return HAL_ERROR;
02038     }
02039     else if (hhash->HashITCounter == 1U)
02040     {
02041       /* This is the first call to HASH_IT, the first input data are about to be
02042          entered in the Peripheral. A specific processing is carried out at this point to
02043          start-up the processing. */
02044       hhash->HashITCounter = 2U;
02045     }
02046     else
02047     {
02048       /* Cruise speed reached, HashITCounter remains equal to 3 until the end of
02049         the HASH processing or the end of the current step for HMAC processing. */
02050       hhash->HashITCounter = 3U;
02051     }
02052 
02053     /* If digest is ready */
02054     if (__HAL_HASH_GET_FLAG(HASH_FLAG_DCIS))
02055     {
02056       /* Read the digest */
02057       HASH_GetDigest(hhash->pHashOutBuffPtr, HASH_DIGEST_LENGTH());
02058 
02059       /* Disable Interrupts */
02060       __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
02061       /* Change the HASH state */
02062       hhash->State = HAL_HASH_STATE_READY;
02063       /* Reset HASH state machine */
02064       hhash->Phase = HAL_HASH_PHASE_READY;
02065       /* Call digest computation complete call back */
02066 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
02067       hhash->DgstCpltCallback(hhash);
02068 #else
02069       HAL_HASH_DgstCpltCallback(hhash);
02070 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
02071 
02072       return HAL_OK;
02073     }
02074 
02075     /* If Peripheral ready to accept new data */
02076     if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))
02077     {
02078 
02079       /* If the suspension flag has been raised and if the processing is not about
02080          to end, suspend processing */
02081       if ((hhash->HashInCount != 0U) && (hhash->SuspendRequest == HAL_HASH_SUSPEND))
02082       {
02083         /* Disable Interrupts */
02084         __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
02085 
02086         /* Reset SuspendRequest */
02087         hhash->SuspendRequest = HAL_HASH_SUSPEND_NONE;
02088 
02089         /* Change the HASH state */
02090         hhash->State = HAL_HASH_STATE_SUSPENDED;
02091 
02092         return HAL_OK;
02093       }
02094 
02095       /* Enter input data in the Peripheral through HASH_Write_Block_Data() call and
02096         check whether the digest calculation has been triggered */
02097       if (HASH_Write_Block_Data(hhash) == HASH_DIGEST_CALCULATION_STARTED)
02098       {
02099         /* Call Input data transfer complete call back
02100            (called at the end of each step for HMAC) */
02101 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
02102         hhash->InCpltCallback(hhash);
02103 #else
02104         HAL_HASH_InCpltCallback(hhash);
02105 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
02106 
02107         if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1)
02108         {
02109           /* Wait until Peripheral is not busy anymore */
02110           if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK)
02111           {
02112             /* Disable Interrupts */
02113             __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
02114             return HAL_TIMEOUT;
02115           }
02116           /* Initialization start for HMAC STEP 2 */
02117           hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_2;        /* Move phase from Step 1 to Step 2 */
02118           __HAL_HASH_SET_NBVALIDBITS(hhash->HashBuffSize);  /* Set NBLW for the input message */
02119           hhash->HashInCount = hhash->HashBuffSize;         /* Set the input data size (in bytes) */
02120           hhash->pHashInBuffPtr = hhash->pHashMsgBuffPtr;   /* Set the input data address */
02121           hhash->HashITCounter = 1;                         /* Set ITCounter to 1 to indicate the start
02122                                                                of a new phase */
02123           __HAL_HASH_ENABLE_IT(HASH_IT_DINI);               /* Enable IT (was disabled in HASH_Write_Block_Data) */
02124         }
02125         else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)
02126         {
02127           /* Wait until Peripheral is not busy anymore */
02128           if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK)
02129           {
02130             /* Disable Interrupts */
02131             __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
02132             return HAL_TIMEOUT;
02133           }
02134           /* Initialization start for HMAC STEP 3 */
02135           hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_3;         /* Move phase from Step 2 to Step 3 */
02136           __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);   /* Set NBLW for the key */
02137           hhash->HashInCount = hhash->Init.KeySize;          /* Set the key size (in bytes) */
02138           hhash->pHashInBuffPtr = hhash->Init.pKey;          /* Set the key address */
02139           hhash->HashITCounter = 1;                          /* Set ITCounter to 1 to indicate the start
02140                                                                 of a new phase */
02141           __HAL_HASH_ENABLE_IT(HASH_IT_DINI);                /* Enable IT (was disabled in HASH_Write_Block_Data) */
02142         }
02143         else
02144         {
02145           /* Nothing to do */
02146         }
02147       } /* if (HASH_Write_Block_Data(hhash) == HASH_DIGEST_CALCULATION_STARTED) */
02148     }  /* if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))*/
02149 
02150     /* Return function status */
02151     return HAL_OK;
02152   }
02153   else
02154   {
02155     return HAL_BUSY;
02156   }
02157 }
02158 
02159 
02160 /**
02161   * @brief  Write a block of data in HASH Peripheral in interruption mode.
02162   * @param  hhash HASH handle.
02163   * @note   HASH_Write_Block_Data() is called under interruption by HASH_IT().
02164   * @retval HAL status
02165   */
02166 static uint32_t HASH_Write_Block_Data(HASH_HandleTypeDef *hhash)
02167 {
02168   uint32_t inputaddr;
02169   uint32_t buffercounter;
02170   uint32_t inputcounter;
02171   uint32_t ret = HASH_DIGEST_CALCULATION_NOT_STARTED;
02172 
02173   /* If there are more than 64 bytes remaining to be entered */
02174   if (hhash->HashInCount > 64U)
02175   {
02176     inputaddr = (uint32_t)hhash->pHashInBuffPtr;
02177     /* Write the Input block in the Data IN register
02178       (16 32-bit words, or 64 bytes are entered) */
02179     for (buffercounter = 0U; buffercounter < 64U; buffercounter += 4U)
02180     {
02181       HASH->DIN = *(uint32_t *)inputaddr;
02182       inputaddr += 4U;
02183     }
02184     /* If this is the start of input data entering, an additional word
02185       must be entered to start up the HASH processing */
02186     if (hhash->HashITCounter == 2U)
02187     {
02188       HASH->DIN = *(uint32_t *)inputaddr;
02189       if (hhash->HashInCount >= 68U)
02190       {
02191         /* There are still data waiting to be entered in the Peripheral.
02192            Decrement buffer counter and set pointer to the proper
02193            memory location for the next data entering round. */
02194         hhash->HashInCount -= 68U;
02195         hhash->pHashInBuffPtr += 68U;
02196       }
02197       else
02198       {
02199         /* All the input buffer has been fed to the HW. */
02200         hhash->HashInCount = 0U;
02201       }
02202     }
02203     else
02204     {
02205       /* 64 bytes have been entered and there are still some remaining:
02206          Decrement buffer counter and set pointer to the proper
02207         memory location for the next data entering round.*/
02208       hhash->HashInCount -= 64U;
02209       hhash->pHashInBuffPtr += 64U;
02210     }
02211   }
02212   else
02213   {
02214     /* 64 or less bytes remain to be entered. This is the last
02215       data entering round. */
02216 
02217     /* Get the buffer address */
02218     inputaddr = (uint32_t)hhash->pHashInBuffPtr;
02219     /* Get the buffer counter */
02220     inputcounter = hhash->HashInCount;
02221     /* Disable Interrupts */
02222     __HAL_HASH_DISABLE_IT(HASH_IT_DINI);
02223 
02224     /* Write the Input block in the Data IN register */
02225     for (buffercounter = 0U; buffercounter < ((inputcounter + 3U) / 4U); buffercounter++)
02226     {
02227       HASH->DIN = *(uint32_t *)inputaddr;
02228       inputaddr += 4U;
02229     }
02230 
02231     if (hhash->Accumulation == 1U)
02232     {
02233       /* Field accumulation is set, API only feeds data to the Peripheral and under interruption.
02234          The digest computation will be started when the last buffer data are entered. */
02235 
02236       /* Reset multi buffers accumulation flag */
02237       hhash->Accumulation = 0U;
02238       /* Change the HASH state */
02239       hhash->State = HAL_HASH_STATE_READY;
02240       /* Call Input data transfer complete call back */
02241 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
02242       hhash->InCpltCallback(hhash);
02243 #else
02244       HAL_HASH_InCpltCallback(hhash);
02245 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
02246     }
02247     else
02248     {
02249       /* Start the Digest calculation */
02250       __HAL_HASH_START_DIGEST();
02251       /* Return indication that digest calculation has started:
02252          this return value triggers the call to Input data transfer
02253          complete call back as well as the proper transition from
02254          one step to another in HMAC mode. */
02255       ret = HASH_DIGEST_CALCULATION_STARTED;
02256     }
02257     /* Reset buffer counter */
02258     hhash->HashInCount = 0;
02259   }
02260 
02261   /* Return whether or digest calculation has started */
02262   return ret;
02263 }
02264 
02265 /**
02266   * @brief  HMAC processing in polling mode.
02267   * @param  hhash HASH handle.
02268   * @param  Timeout Timeout value.
02269   * @retval HAL status
02270   */
02271 static HAL_StatusTypeDef HMAC_Processing(HASH_HandleTypeDef *hhash, uint32_t Timeout)
02272 {
02273   /* Ensure first that Phase is correct */
02274   if ((hhash->Phase != HAL_HASH_PHASE_HMAC_STEP_1) && (hhash->Phase != HAL_HASH_PHASE_HMAC_STEP_2)
02275       && (hhash->Phase != HAL_HASH_PHASE_HMAC_STEP_3))
02276   {
02277     /* Change the HASH state */
02278     hhash->State = HAL_HASH_STATE_READY;
02279 
02280     /* Process Unlock */
02281     __HAL_UNLOCK(hhash);
02282 
02283     /* Return function status */
02284     return HAL_ERROR;
02285   }
02286 
02287   /* HMAC Step 1 processing */
02288   if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1)
02289   {
02290     /************************** STEP 1 ******************************************/
02291     /* Configure the Number of valid bits in last word of the message */
02292     __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
02293 
02294     /* Write input buffer in Data register */
02295     hhash->Status = HASH_WriteData(hhash, hhash->pHashKeyBuffPtr, hhash->HashKeyCount);
02296     if (hhash->Status != HAL_OK)
02297     {
02298       return hhash->Status;
02299     }
02300 
02301     /* Check whether or not key entering process has been suspended */
02302     if (hhash->State == HAL_HASH_STATE_SUSPENDED)
02303     {
02304       /* Process Unlocked */
02305       __HAL_UNLOCK(hhash);
02306 
02307       /* Stop right there and return function status */
02308       return HAL_OK;
02309     }
02310 
02311     /* No processing suspension at this point: set DCAL bit. */
02312     __HAL_HASH_START_DIGEST();
02313 
02314     /* Wait for BUSY flag to be cleared */
02315     if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, Timeout) != HAL_OK)
02316     {
02317       return HAL_TIMEOUT;
02318     }
02319 
02320     /* Move from Step 1 to Step 2 */
02321     hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_2;
02322 
02323   }
02324 
02325   /* HMAC Step 2 processing.
02326      After phase check, HMAC_Processing() may
02327      - directly start up from this point in resumption case
02328        if the same Step 2 processing was suspended previously
02329     - or fall through from the Step 1 processing carried out hereabove */
02330   if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)
02331   {
02332     /************************** STEP 2 ******************************************/
02333     /* Configure the Number of valid bits in last word of the message */
02334     __HAL_HASH_SET_NBVALIDBITS(hhash->HashBuffSize);
02335 
02336     /* Write input buffer in Data register */
02337     hhash->Status = HASH_WriteData(hhash, hhash->pHashInBuffPtr, hhash->HashInCount);
02338     if (hhash->Status != HAL_OK)
02339     {
02340       return hhash->Status;
02341     }
02342 
02343     /* Check whether or not data entering process has been suspended */
02344     if (hhash->State == HAL_HASH_STATE_SUSPENDED)
02345     {
02346       /* Process Unlocked */
02347       __HAL_UNLOCK(hhash);
02348 
02349       /* Stop right there and return function status */
02350       return HAL_OK;
02351     }
02352 
02353     /* No processing suspension at this point: set DCAL bit. */
02354     __HAL_HASH_START_DIGEST();
02355 
02356     /* Wait for BUSY flag to be cleared */
02357     if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, Timeout) != HAL_OK)
02358     {
02359       return HAL_TIMEOUT;
02360     }
02361 
02362     /* Move from Step 2 to Step 3 */
02363     hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_3;
02364     /* In case Step 1 phase was suspended then resumed,
02365        set again Key input buffers and size before moving to
02366        next step */
02367     hhash->pHashKeyBuffPtr = hhash->Init.pKey;
02368     hhash->HashKeyCount    = hhash->Init.KeySize;
02369   }
02370 
02371 
02372   /* HMAC Step 3 processing.
02373       After phase check, HMAC_Processing() may
02374       - directly start up from this point in resumption case
02375         if the same Step 3 processing was suspended previously
02376      - or fall through from the Step 2 processing carried out hereabove */
02377   if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3)
02378   {
02379     /************************** STEP 3 ******************************************/
02380     /* Configure the Number of valid bits in last word of the message */
02381     __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
02382 
02383     /* Write input buffer in Data register */
02384     hhash->Status = HASH_WriteData(hhash, hhash->pHashKeyBuffPtr, hhash->HashKeyCount);
02385     if (hhash->Status != HAL_OK)
02386     {
02387       return hhash->Status;
02388     }
02389 
02390     /* Check whether or not key entering process has been suspended */
02391     if (hhash->State == HAL_HASH_STATE_SUSPENDED)
02392     {
02393       /* Process Unlocked */
02394       __HAL_UNLOCK(hhash);
02395 
02396       /* Stop right there and return function status */
02397       return HAL_OK;
02398     }
02399 
02400     /* No processing suspension at this point: start the Digest calculation. */
02401     __HAL_HASH_START_DIGEST();
02402 
02403     /* Wait for DCIS flag to be set */
02404     if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_DCIS, RESET, Timeout) != HAL_OK)
02405     {
02406       return HAL_TIMEOUT;
02407     }
02408 
02409     /* Read the message digest */
02410     HASH_GetDigest(hhash->pHashOutBuffPtr, HASH_DIGEST_LENGTH());
02411 
02412     /* Reset HASH state machine */
02413     hhash->Phase = HAL_HASH_PHASE_READY;
02414   }
02415 
02416   /* Change the HASH state */
02417   hhash->State = HAL_HASH_STATE_READY;
02418 
02419   /* Process Unlock */
02420   __HAL_UNLOCK(hhash);
02421 
02422   /* Return function status */
02423   return HAL_OK;
02424 }
02425 
02426 
02427 /**
02428   * @brief  Initialize the HASH peripheral, next process pInBuffer then
02429   *         read the computed digest.
02430   * @note   Digest is available in pOutBuffer.
02431   * @param  hhash HASH handle.
02432   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
02433   * @param  Size length of the input buffer in bytes.
02434   * @param  pOutBuffer pointer to the computed digest.
02435   * @param  Timeout Timeout value.
02436   * @param  Algorithm HASH algorithm.
02437   * @retval HAL status
02438   */
02439 HAL_StatusTypeDef HASH_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer,
02440                              uint32_t Timeout, uint32_t Algorithm)
02441 {
02442   uint8_t *pInBuffer_tmp;  /* input data address, input parameter of HASH_WriteData()         */
02443   uint32_t Size_tmp; /* input data size (in bytes), input parameter of HASH_WriteData() */
02444   HAL_HASH_StateTypeDef State_tmp = hhash->State;
02445 
02446 
02447   /* Initiate HASH processing in case of start or resumption */
02448   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
02449   {
02450     /* Check input parameters */
02451     if ((pInBuffer == NULL) || (pOutBuffer == NULL))
02452     {
02453       hhash->State = HAL_HASH_STATE_READY;
02454       return  HAL_ERROR;
02455     }
02456 
02457     /* Process Locked */
02458     __HAL_LOCK(hhash);
02459 
02460     /* Check if initialization phase has not been already performed */
02461     if (hhash->Phase == HAL_HASH_PHASE_READY)
02462     {
02463       /* Change the HASH state */
02464       hhash->State = HAL_HASH_STATE_BUSY;
02465 
02466       /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
02467       MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT);
02468 
02469       /* Configure the number of valid bits in last word of the message */
02470       __HAL_HASH_SET_NBVALIDBITS(Size);
02471 
02472       /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as
02473       input parameters of HASH_WriteData() */
02474       pInBuffer_tmp = pInBuffer;   /* pInBuffer_tmp is set to the input data address */
02475       Size_tmp = Size;             /* Size_tmp contains the input data size in bytes */
02476 
02477       /* Set the phase */
02478       hhash->Phase = HAL_HASH_PHASE_PROCESS;
02479     }
02480     else if (hhash->Phase == HAL_HASH_PHASE_PROCESS)
02481     {
02482       /* if the Peripheral has already been initialized, two cases are possible */
02483 
02484       /* Process resumption time ... */
02485       if (hhash->State == HAL_HASH_STATE_SUSPENDED)
02486       {
02487         /* Since this is resumption, pInBuffer_tmp and Size_tmp are not set
02488         to the API input parameters but to those saved beforehand by HASH_WriteData()
02489         when the processing was suspended */
02490         pInBuffer_tmp = hhash->pHashInBuffPtr;
02491         Size_tmp = hhash->HashInCount;
02492       }
02493       /* ... or multi-buffer HASH processing end */
02494       else
02495       {
02496         /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as
02497         input parameters of HASH_WriteData() */
02498         pInBuffer_tmp = pInBuffer;
02499         Size_tmp = Size;
02500         /* Configure the number of valid bits in last word of the message */
02501         __HAL_HASH_SET_NBVALIDBITS(Size);
02502       }
02503       /* Change the HASH state */
02504       hhash->State = HAL_HASH_STATE_BUSY;
02505     }
02506     else
02507     {
02508       /* Phase error */
02509       hhash->State = HAL_HASH_STATE_READY;
02510 
02511       /* Process Unlocked */
02512       __HAL_UNLOCK(hhash);
02513 
02514       /* Return function status */
02515       return HAL_ERROR;
02516     }
02517 
02518 
02519     /* Write input buffer in Data register */
02520     hhash->Status = HASH_WriteData(hhash, pInBuffer_tmp, Size_tmp);
02521     if (hhash->Status != HAL_OK)
02522     {
02523       return hhash->Status;
02524     }
02525 
02526     /* If the process has not been suspended, carry on to digest calculation */
02527     if (hhash->State != HAL_HASH_STATE_SUSPENDED)
02528     {
02529       /* Start the Digest calculation */
02530       __HAL_HASH_START_DIGEST();
02531 
02532       /* Wait for DCIS flag to be set */
02533       if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_DCIS, RESET, Timeout) != HAL_OK)
02534       {
02535         return HAL_TIMEOUT;
02536       }
02537 
02538       /* Read the message digest */
02539       HASH_GetDigest(pOutBuffer, HASH_DIGEST_LENGTH());
02540 
02541       /* Change the HASH state */
02542       hhash->State = HAL_HASH_STATE_READY;
02543 
02544       /* Reset HASH state machine */
02545       hhash->Phase = HAL_HASH_PHASE_READY;
02546 
02547     }
02548 
02549     /* Process Unlocked */
02550     __HAL_UNLOCK(hhash);
02551 
02552     /* Return function status */
02553     return HAL_OK;
02554 
02555   }
02556   else
02557   {
02558     return HAL_BUSY;
02559   }
02560 }
02561 
02562 
02563 /**
02564   * @brief  If not already done, initialize the HASH peripheral then
02565   *         processes pInBuffer.
02566   * @note   Field hhash->Phase of HASH handle is tested to check whether or not
02567   *         the Peripheral has already been initialized.
02568   * @note   The input buffer size (in bytes) must be a multiple of 4 otherwise, the
02569   *         HASH digest computation is corrupted.
02570   * @param  hhash HASH handle.
02571   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
02572   * @param  Size length of the input buffer in bytes, must be a multiple of 4.
02573   * @param  Algorithm HASH algorithm.
02574   * @retval HAL status
02575   */
02576 HAL_StatusTypeDef HASH_Accumulate(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm)
02577 {
02578   uint8_t *pInBuffer_tmp;   /* input data address, input parameter of HASH_WriteData()         */
02579   uint32_t Size_tmp;  /* input data size (in bytes), input parameter of HASH_WriteData() */
02580   HAL_HASH_StateTypeDef State_tmp = hhash->State;
02581 
02582   /* Make sure the input buffer size (in bytes) is a multiple of 4 */
02583   if ((Size % 4U) != 0U)
02584   {
02585     return  HAL_ERROR;
02586   }
02587 
02588   /* Initiate HASH processing in case of start or resumption */
02589   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
02590   {
02591     /* Check input parameters */
02592     if ((pInBuffer == NULL) || (Size == 0U))
02593     {
02594       hhash->State = HAL_HASH_STATE_READY;
02595       return  HAL_ERROR;
02596     }
02597 
02598     /* Process Locked */
02599     __HAL_LOCK(hhash);
02600 
02601     /* If resuming the HASH processing */
02602     if (hhash->State == HAL_HASH_STATE_SUSPENDED)
02603     {
02604       /* Change the HASH state */
02605       hhash->State = HAL_HASH_STATE_BUSY;
02606 
02607       /* Since this is resumption, pInBuffer_tmp and Size_tmp are not set
02608          to the API input parameters but to those saved beforehand by HASH_WriteData()
02609          when the processing was suspended */
02610       pInBuffer_tmp = hhash->pHashInBuffPtr;  /* pInBuffer_tmp is set to the input data address */
02611       Size_tmp = hhash->HashInCount;          /* Size_tmp contains the input data size in bytes */
02612 
02613     }
02614     else
02615     {
02616       /* Change the HASH state */
02617       hhash->State = HAL_HASH_STATE_BUSY;
02618 
02619       /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as
02620          input parameters of HASH_WriteData() */
02621       pInBuffer_tmp = pInBuffer;    /* pInBuffer_tmp is set to the input data address */
02622       Size_tmp = Size;              /* Size_tmp contains the input data size in bytes */
02623 
02624       /* Check if initialization phase has already be performed */
02625       if (hhash->Phase == HAL_HASH_PHASE_READY)
02626       {
02627         /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
02628         MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT);
02629       }
02630 
02631       /* Set the phase */
02632       hhash->Phase = HAL_HASH_PHASE_PROCESS;
02633 
02634     }
02635 
02636     /* Write input buffer in Data register */
02637     hhash->Status = HASH_WriteData(hhash, pInBuffer_tmp, Size_tmp);
02638     if (hhash->Status != HAL_OK)
02639     {
02640       return hhash->Status;
02641     }
02642 
02643     /* If the process has not been suspended, move the state to Ready */
02644     if (hhash->State != HAL_HASH_STATE_SUSPENDED)
02645     {
02646       /* Change the HASH state */
02647       hhash->State = HAL_HASH_STATE_READY;
02648     }
02649 
02650     /* Process Unlocked */
02651     __HAL_UNLOCK(hhash);
02652 
02653     /* Return function status */
02654     return HAL_OK;
02655 
02656   }
02657   else
02658   {
02659     return HAL_BUSY;
02660   }
02661 
02662 
02663 }
02664 
02665 
02666 /**
02667   * @brief  If not already done, initialize the HASH peripheral then
02668   *         processes pInBuffer in interruption mode.
02669   * @note   Field hhash->Phase of HASH handle is tested to check whether or not
02670   *         the Peripheral has already been initialized.
02671   * @note   The input buffer size (in bytes) must be a multiple of 4 otherwise, the
02672   *         HASH digest computation is corrupted.
02673   * @param  hhash HASH handle.
02674   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
02675   * @param  Size length of the input buffer in bytes, must be a multiple of 4.
02676   * @param  Algorithm HASH algorithm.
02677   * @retval HAL status
02678   */
02679 HAL_StatusTypeDef HASH_Accumulate_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm)
02680 {
02681   HAL_HASH_StateTypeDef State_tmp = hhash->State;
02682   __IO uint32_t inputaddr = (uint32_t) pInBuffer;
02683   uint32_t SizeVar = Size;
02684 
02685   /* Make sure the input buffer size (in bytes) is a multiple of 4 */
02686   if ((Size % 4U) != 0U)
02687   {
02688     return  HAL_ERROR;
02689   }
02690 
02691   /* Initiate HASH processing in case of start or resumption */
02692   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
02693   {
02694     /* Check input parameters */
02695     if ((pInBuffer == NULL) || (Size == 0U))
02696     {
02697       hhash->State = HAL_HASH_STATE_READY;
02698       return  HAL_ERROR;
02699     }
02700 
02701     /* Process Locked */
02702     __HAL_LOCK(hhash);
02703 
02704     /* If resuming the HASH processing */
02705     if (hhash->State == HAL_HASH_STATE_SUSPENDED)
02706     {
02707       /* Change the HASH state */
02708       hhash->State = HAL_HASH_STATE_BUSY;
02709     }
02710     else
02711     {
02712       /* Change the HASH state */
02713       hhash->State = HAL_HASH_STATE_BUSY;
02714 
02715       /* Check if initialization phase has already be performed */
02716       if (hhash->Phase == HAL_HASH_PHASE_READY)
02717       {
02718         /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
02719         MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT);
02720         hhash->HashITCounter = 1;
02721       }
02722       else
02723       {
02724         hhash->HashITCounter = 3; /* 'cruise-speed' reached during a previous buffer processing */
02725       }
02726 
02727       /* Set the phase */
02728       hhash->Phase = HAL_HASH_PHASE_PROCESS;
02729 
02730       /* If DINIS is equal to 0 (for example if an incomplete block has been previously
02731        fed to the Peripheral), the DINIE interruption won't be triggered when DINIE is set.
02732        Therefore, first words are manually entered until DINIS raises, or until there
02733        is not more data to enter. */
02734       while ((!(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))) && (SizeVar > 0U))
02735       {
02736 
02737         /* Write input data 4 bytes at a time */
02738         HASH->DIN = *(uint32_t *)inputaddr;
02739         inputaddr += 4U;
02740         SizeVar -= 4U;
02741       }
02742 
02743       /* If DINIS is still not set or if all the data have been fed, stop here */
02744       if ((!(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))) || (SizeVar == 0U))
02745       {
02746         /* Change the HASH state */
02747         hhash->State = HAL_HASH_STATE_READY;
02748 
02749         /* Process Unlock */
02750         __HAL_UNLOCK(hhash);
02751 
02752         /* Return function status */
02753         return HAL_OK;
02754       }
02755 
02756       /* otherwise, carry on in interrupt-mode */
02757       hhash->HashInCount = SizeVar;               /* Counter used to keep track of number of data
02758                                                   to be fed to the Peripheral */
02759       hhash->pHashInBuffPtr = (uint8_t *)inputaddr;       /* Points at data which will be fed to the Peripheral at
02760                                                   the next interruption */
02761       /* In case of suspension, hhash->HashInCount and hhash->pHashInBuffPtr contain
02762          the information describing where the HASH process is stopped.
02763          These variables are used later on to resume the HASH processing at the
02764          correct location. */
02765 
02766     }
02767 
02768     /* Set multi buffers accumulation flag */
02769     hhash->Accumulation = 1U;
02770 
02771     /* Process Unlock */
02772     __HAL_UNLOCK(hhash);
02773 
02774     /* Enable Data Input interrupt */
02775     __HAL_HASH_ENABLE_IT(HASH_IT_DINI);
02776 
02777     /* Return function status */
02778     return HAL_OK;
02779 
02780   }
02781   else
02782   {
02783     return HAL_BUSY;
02784   }
02785 
02786 }
02787 
02788 
02789 
02790 /**
02791   * @brief  Initialize the HASH peripheral, next process pInBuffer then
02792   *         read the computed digest in interruption mode.
02793   * @note   Digest is available in pOutBuffer.
02794   * @param  hhash HASH handle.
02795   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
02796   * @param  Size length of the input buffer in bytes.
02797   * @param  pOutBuffer pointer to the computed digest.
02798   * @param  Algorithm HASH algorithm.
02799   * @retval HAL status
02800   */
02801 HAL_StatusTypeDef HASH_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer,
02802                                 uint32_t Algorithm)
02803 {
02804   HAL_HASH_StateTypeDef State_tmp = hhash->State;
02805   __IO uint32_t inputaddr = (uint32_t) pInBuffer;
02806   uint32_t polling_step = 0U;
02807   uint32_t initialization_skipped = 0U;
02808   uint32_t SizeVar = Size;
02809 
02810   /* If State is ready or suspended, start or resume IT-based HASH processing */
02811   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
02812   {
02813     /* Check input parameters */
02814     if ((pInBuffer == NULL) || (Size == 0U) || (pOutBuffer == NULL))
02815     {
02816       hhash->State = HAL_HASH_STATE_READY;
02817       return  HAL_ERROR;
02818     }
02819 
02820     /* Process Locked */
02821     __HAL_LOCK(hhash);
02822 
02823     /* Change the HASH state */
02824     hhash->State = HAL_HASH_STATE_BUSY;
02825 
02826     /* Initialize IT counter */
02827     hhash->HashITCounter = 1;
02828 
02829     /* Check if initialization phase has already be performed */
02830     if (hhash->Phase == HAL_HASH_PHASE_READY)
02831     {
02832       /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
02833       MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT);
02834 
02835       /* Configure the number of valid bits in last word of the message */
02836       __HAL_HASH_SET_NBVALIDBITS(SizeVar);
02837 
02838 
02839       hhash->HashInCount = SizeVar;            /* Counter used to keep track of number of data
02840                                                   to be fed to the Peripheral */
02841       hhash->pHashInBuffPtr = pInBuffer;       /* Points at data which will be fed to the Peripheral at
02842                                                   the next interruption */
02843       /* In case of suspension, hhash->HashInCount and hhash->pHashInBuffPtr contain
02844          the information describing where the HASH process is stopped.
02845          These variables are used later on to resume the HASH processing at the
02846          correct location. */
02847 
02848       hhash->pHashOutBuffPtr = pOutBuffer;     /* Points at the computed digest */
02849     }
02850     else
02851     {
02852       initialization_skipped = 1; /* info user later on in case of multi-buffer */
02853     }
02854 
02855     /* Set the phase */
02856     hhash->Phase = HAL_HASH_PHASE_PROCESS;
02857 
02858     /* If DINIS is equal to 0 (for example if an incomplete block has been previously
02859       fed to the Peripheral), the DINIE interruption won't be triggered when DINIE is set.
02860       Therefore, first words are manually entered until DINIS raises. */
02861     while ((!(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))) && (SizeVar > 3U))
02862     {
02863       polling_step = 1U; /* note that some words are entered before enabling the interrupt */
02864 
02865       /* Write input data 4 bytes at a time */
02866       HASH->DIN = *(uint32_t *)inputaddr;
02867       inputaddr += 4U;
02868       SizeVar -= 4U;
02869     }
02870 
02871     if (polling_step == 1U)
02872     {
02873       if (SizeVar == 0U)
02874       {
02875         /* If all the data have been entered at this point, it only remains to
02876          read the digest */
02877         hhash->pHashOutBuffPtr = pOutBuffer;     /* Points at the computed digest */
02878 
02879         /* Start the Digest calculation */
02880         __HAL_HASH_START_DIGEST();
02881         /* Process Unlock */
02882         __HAL_UNLOCK(hhash);
02883 
02884         /* Enable Interrupts */
02885         __HAL_HASH_ENABLE_IT(HASH_IT_DCI);
02886 
02887         /* Return function status */
02888         return HAL_OK;
02889       }
02890       else if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))
02891       {
02892         /* It remains data to enter and the Peripheral is ready to trigger DINIE,
02893            carry on as usual.
02894            Update HashInCount and pHashInBuffPtr accordingly. */
02895         hhash->HashInCount = SizeVar;
02896         hhash->pHashInBuffPtr = (uint8_t *)inputaddr;
02897         /* Update the configuration of the number of valid bits in last word of the message */
02898         __HAL_HASH_SET_NBVALIDBITS(SizeVar);
02899         hhash->pHashOutBuffPtr = pOutBuffer;  /* Points at the computed digest */
02900         if (initialization_skipped == 1U)
02901         {
02902           hhash->HashITCounter = 3; /* 'cruise-speed' reached during a previous buffer processing */
02903         }
02904       }
02905       else
02906       {
02907         /* DINIS is not set but it remains a few data to enter (not enough for a full word).
02908            Manually enter the last bytes before enabling DCIE. */
02909         __HAL_HASH_SET_NBVALIDBITS(SizeVar);
02910         HASH->DIN = *(uint32_t *)inputaddr;
02911 
02912         /* Start the Digest calculation */
02913         hhash->pHashOutBuffPtr = pOutBuffer;     /* Points at the computed digest */
02914         __HAL_HASH_START_DIGEST();
02915         /* Process Unlock */
02916         __HAL_UNLOCK(hhash);
02917 
02918         /* Enable Interrupts */
02919         __HAL_HASH_ENABLE_IT(HASH_IT_DCI);
02920 
02921         /* Return function status */
02922         return HAL_OK;
02923       }
02924     } /*  if (polling_step == 1) */
02925 
02926 
02927     /* Process Unlock */
02928     __HAL_UNLOCK(hhash);
02929 
02930     /* Enable Interrupts */
02931     __HAL_HASH_ENABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
02932 
02933     /* Return function status */
02934     return HAL_OK;
02935   }
02936   else
02937   {
02938     return HAL_BUSY;
02939   }
02940 
02941 }
02942 
02943 
02944 /**
02945   * @brief  Initialize the HASH peripheral then initiate a DMA transfer
02946   *         to feed the input buffer to the Peripheral.
02947   * @note   If MDMAT bit is set before calling this function (multi-buffer
02948   *          HASH processing case), the input buffer size (in bytes) must be
02949   *          a multiple of 4 otherwise, the HASH digest computation is corrupted.
02950   *          For the processing of the last buffer of the thread, MDMAT bit must
02951   *          be reset and the buffer length (in bytes) doesn't have to be a
02952   *          multiple of 4.
02953   * @param  hhash HASH handle.
02954   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
02955   * @param  Size length of the input buffer in bytes.
02956   * @param  Algorithm HASH algorithm.
02957   * @retval HAL status
02958   */
02959 HAL_StatusTypeDef HASH_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm)
02960 {
02961   uint32_t inputaddr;
02962   uint32_t inputSize;
02963   HAL_StatusTypeDef status ;
02964   HAL_HASH_StateTypeDef State_tmp = hhash->State;
02965 
02966 #if defined (HASH_CR_MDMAT)
02967   /* Make sure the input buffer size (in bytes) is a multiple of 4 when MDMAT bit is set
02968      (case of multi-buffer HASH processing) */
02969   assert_param(IS_HASH_DMA_MULTIBUFFER_SIZE(Size));
02970 #endif /* MDMA defined*/
02971   /* If State is ready or suspended, start or resume polling-based HASH processing */
02972   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
02973   {
02974     /* Check input parameters */
02975     if ((pInBuffer == NULL) || (Size == 0U) ||
02976         /* Check phase coherency. Phase must be
02977            either READY (fresh start)
02978            or PROCESS (multi-buffer HASH management) */
02979         ((hhash->Phase != HAL_HASH_PHASE_READY) && (!(IS_HASH_PROCESSING(hhash)))))
02980     {
02981       hhash->State = HAL_HASH_STATE_READY;
02982       return  HAL_ERROR;
02983     }
02984 
02985 
02986     /* Process Locked */
02987     __HAL_LOCK(hhash);
02988 
02989     /* If not a resumption case */
02990     if (hhash->State == HAL_HASH_STATE_READY)
02991     {
02992       /* Change the HASH state */
02993       hhash->State = HAL_HASH_STATE_BUSY;
02994 
02995       /* Check if initialization phase has already been performed.
02996          If Phase is already set to HAL_HASH_PHASE_PROCESS, this means the
02997          API is processing a new input data message in case of multi-buffer HASH
02998          computation. */
02999       if (hhash->Phase == HAL_HASH_PHASE_READY)
03000       {
03001         /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
03002         MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT);
03003 
03004         /* Set the phase */
03005         hhash->Phase = HAL_HASH_PHASE_PROCESS;
03006       }
03007 
03008       /* Configure the Number of valid bits in last word of the message */
03009       __HAL_HASH_SET_NBVALIDBITS(Size);
03010 
03011       inputaddr = (uint32_t)pInBuffer;     /* DMA transfer start address   */
03012       inputSize = Size;                    /* DMA transfer size (in bytes) */
03013 
03014       /* In case of suspension request, save the starting parameters */
03015       hhash->pHashInBuffPtr =  pInBuffer;  /* DMA transfer start address   */
03016       hhash->HashInCount = Size;           /* DMA transfer size (in bytes) */
03017 
03018     }
03019     /* If resumption case */
03020     else
03021     {
03022       /* Change the HASH state */
03023       hhash->State = HAL_HASH_STATE_BUSY;
03024 
03025       /* Resumption case, inputaddr and inputSize are not set to the API input parameters
03026          but to those saved beforehand by HAL_HASH_DMAFeed_ProcessSuspend() when the
03027          processing was suspended */
03028       inputaddr = (uint32_t)hhash->pHashInBuffPtr;  /* DMA transfer start address   */
03029       inputSize = hhash->HashInCount;               /* DMA transfer size (in bytes) */
03030 
03031     }
03032 
03033     /* Set the HASH DMA transfer complete callback */
03034     hhash->hdmain->XferCpltCallback = HASH_DMAXferCplt;
03035     /* Set the DMA error callback */
03036     hhash->hdmain->XferErrorCallback = HASH_DMAError;
03037 
03038     /* Store number of words already pushed to manage proper DMA processing suspension */
03039     hhash->NbWordsAlreadyPushed = HASH_NBW_PUSHED();
03040 
03041     /* Enable the DMA In DMA channel */
03042     status = HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, \
03043                               (((inputSize % 4U) != 0U) ? ((inputSize + (4U - (inputSize % 4U))) / 4U) : \
03044                                (inputSize / 4U)));
03045 
03046     /* Enable DMA requests */
03047     SET_BIT(HASH->CR, HASH_CR_DMAE);
03048 
03049     /* Process Unlock */
03050     __HAL_UNLOCK(hhash);
03051 
03052     /* Return function status */
03053     if (status != HAL_OK)
03054     {
03055       /* Update HASH state machine to error */
03056       hhash->State = HAL_HASH_STATE_ERROR;
03057     }
03058 
03059     return status;
03060   }
03061   else
03062   {
03063     return HAL_BUSY;
03064   }
03065 }
03066 
03067 /**
03068   * @brief  Return the computed digest.
03069   * @note   The API waits for DCIS to be set then reads the computed digest.
03070   * @param  hhash HASH handle.
03071   * @param  pOutBuffer pointer to the computed digest.
03072   * @param  Timeout Timeout value.
03073   * @retval HAL status
03074   */
03075 HAL_StatusTypeDef HASH_Finish(HASH_HandleTypeDef *hhash, uint8_t *pOutBuffer, uint32_t Timeout)
03076 {
03077 
03078   if (hhash->State == HAL_HASH_STATE_READY)
03079   {
03080     /* Check parameter */
03081     if (pOutBuffer == NULL)
03082     {
03083       return  HAL_ERROR;
03084     }
03085 
03086     /* Process Locked */
03087     __HAL_LOCK(hhash);
03088 
03089     /* Change the HASH state to busy */
03090     hhash->State = HAL_HASH_STATE_BUSY;
03091 
03092     /* Wait for DCIS flag to be set */
03093     if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_DCIS, RESET, Timeout) != HAL_OK)
03094     {
03095       return HAL_TIMEOUT;
03096     }
03097 
03098     /* Read the message digest */
03099     HASH_GetDigest(pOutBuffer, HASH_DIGEST_LENGTH());
03100 
03101     /* Change the HASH state to ready */
03102     hhash->State = HAL_HASH_STATE_READY;
03103 
03104     /* Reset HASH state machine */
03105     hhash->Phase = HAL_HASH_PHASE_READY;
03106 
03107     /* Process UnLock */
03108     __HAL_UNLOCK(hhash);
03109 
03110     /* Return function status */
03111     return HAL_OK;
03112 
03113   }
03114   else
03115   {
03116     return HAL_BUSY;
03117   }
03118 
03119 }
03120 
03121 
03122 /**
03123   * @brief  Initialize the HASH peripheral in HMAC mode, next process pInBuffer then
03124   *         read the computed digest.
03125   * @note   Digest is available in pOutBuffer.
03126   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
03127   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
03128   * @param  hhash HASH handle.
03129   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
03130   * @param  Size length of the input buffer in bytes.
03131   * @param  pOutBuffer pointer to the computed digest.
03132   * @param  Timeout Timeout value.
03133   * @param  Algorithm HASH algorithm.
03134   * @retval HAL status
03135   */
03136 HAL_StatusTypeDef HMAC_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer,
03137                              uint32_t Timeout, uint32_t Algorithm)
03138 {
03139   HAL_HASH_StateTypeDef State_tmp = hhash->State;
03140 
03141   /* If State is ready or suspended, start or resume polling-based HASH processing */
03142   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
03143   {
03144     /* Check input parameters */
03145     if ((pInBuffer == NULL) || (Size == 0U) || (hhash->Init.pKey == NULL) || (hhash->Init.KeySize == 0U)
03146         || (pOutBuffer == NULL))
03147     {
03148       hhash->State = HAL_HASH_STATE_READY;
03149       return  HAL_ERROR;
03150     }
03151 
03152     /* Process Locked */
03153     __HAL_LOCK(hhash);
03154 
03155     /* Change the HASH state */
03156     hhash->State = HAL_HASH_STATE_BUSY;
03157 
03158     /* Check if initialization phase has already be performed */
03159     if (hhash->Phase == HAL_HASH_PHASE_READY)
03160     {
03161       /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits */
03162       if (hhash->Init.KeySize > 64U)
03163       {
03164         MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
03165                    Algorithm | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT);
03166       }
03167       else
03168       {
03169         MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
03170                    Algorithm | HASH_ALGOMODE_HMAC | HASH_CR_INIT);
03171       }
03172       /* Set the phase to Step 1 */
03173       hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_1;
03174       /* Resort to hhash internal fields to feed the Peripheral.
03175          Parameters will be updated in case of suspension to contain the proper
03176          information at resumption time. */
03177       hhash->pHashOutBuffPtr  = pOutBuffer;            /* Output digest address    */
03178       hhash->pHashInBuffPtr   = pInBuffer;             /* Input data address, HMAC_Processing input
03179                                                           parameter for Step 2     */
03180       hhash->HashInCount      = Size;                  /* Input data size, HMAC_Processing input
03181                                                           parameter for Step 2        */
03182       hhash->HashBuffSize     = Size;                  /* Store the input buffer size for the whole HMAC process*/
03183       hhash->pHashKeyBuffPtr  = hhash->Init.pKey;      /* Key address, HMAC_Processing input parameter for Step
03184                                                           1 and Step 3 */
03185       hhash->HashKeyCount     = hhash->Init.KeySize;   /* Key size, HMAC_Processing input parameter for Step 1
03186                                                           and Step 3    */
03187     }
03188 
03189     /* Carry out HMAC processing */
03190     return HMAC_Processing(hhash, Timeout);
03191 
03192   }
03193   else
03194   {
03195     return HAL_BUSY;
03196   }
03197 }
03198 
03199 
03200 
03201 /**
03202   * @brief  Initialize the HASH peripheral in HMAC mode, next process pInBuffer then
03203   *         read the computed digest in interruption mode.
03204   * @note   Digest is available in pOutBuffer.
03205   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
03206   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
03207   * @param  hhash HASH handle.
03208   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
03209   * @param  Size length of the input buffer in bytes.
03210   * @param  pOutBuffer pointer to the computed digest.
03211   * @param  Algorithm HASH algorithm.
03212   * @retval HAL status
03213   */
03214 HAL_StatusTypeDef HMAC_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer,
03215                                 uint32_t Algorithm)
03216 {
03217   HAL_HASH_StateTypeDef State_tmp = hhash->State;
03218 
03219   /* If State is ready or suspended, start or resume IT-based HASH processing */
03220   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
03221   {
03222     /* Check input parameters */
03223     if ((pInBuffer == NULL) || (Size == 0U) || (hhash->Init.pKey == NULL) || (hhash->Init.KeySize == 0U)
03224         || (pOutBuffer == NULL))
03225     {
03226       hhash->State = HAL_HASH_STATE_READY;
03227       return  HAL_ERROR;
03228     }
03229 
03230     /* Process Locked */
03231     __HAL_LOCK(hhash);
03232 
03233     /* Change the HASH state */
03234     hhash->State = HAL_HASH_STATE_BUSY;
03235 
03236     /* Initialize IT counter */
03237     hhash->HashITCounter = 1;
03238 
03239     /* Check if initialization phase has already be performed */
03240     if (hhash->Phase == HAL_HASH_PHASE_READY)
03241     {
03242       /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits */
03243       if (hhash->Init.KeySize > 64U)
03244       {
03245         MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
03246                    Algorithm | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT);
03247       }
03248       else
03249       {
03250         MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
03251                    Algorithm | HASH_ALGOMODE_HMAC | HASH_CR_INIT);
03252       }
03253 
03254       /* Resort to hhash internal fields hhash->pHashInBuffPtr and hhash->HashInCount
03255          to feed the Peripheral whatever the HMAC step.
03256          Lines below are set to start HMAC Step 1 processing where key is entered first. */
03257       hhash->HashInCount     = hhash->Init.KeySize; /* Key size                      */
03258       hhash->pHashInBuffPtr  = hhash->Init.pKey ;   /* Key address                   */
03259 
03260       /* Store input and output parameters in handle fields to manage steps transition
03261          or possible HMAC suspension/resumption */
03262       hhash->pHashKeyBuffPtr = hhash->Init.pKey;    /* Key address                   */
03263       hhash->pHashMsgBuffPtr = pInBuffer;           /* Input message address         */
03264       hhash->HashBuffSize    = Size;                /* Input message size (in bytes) */
03265       hhash->pHashOutBuffPtr = pOutBuffer;          /* Output digest address         */
03266 
03267       /* Configure the number of valid bits in last word of the key */
03268       __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
03269 
03270       /* Set the phase to Step 1 */
03271       hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_1;
03272     }
03273     else if ((hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1) || (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3))
03274     {
03275       /* Restart IT-based HASH processing after Step 1 or Step 3 suspension */
03276 
03277     }
03278     else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)
03279     {
03280       /* Restart IT-based HASH processing after Step 2 suspension */
03281 
03282     }
03283     else
03284     {
03285       /* Error report as phase incorrect */
03286       /* Process Unlock */
03287       __HAL_UNLOCK(hhash);
03288       hhash->State = HAL_HASH_STATE_READY;
03289       return HAL_ERROR;
03290     }
03291 
03292     /* Process Unlock */
03293     __HAL_UNLOCK(hhash);
03294 
03295     /* Enable Interrupts */
03296     __HAL_HASH_ENABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
03297 
03298     /* Return function status */
03299     return HAL_OK;
03300   }
03301   else
03302   {
03303     return HAL_BUSY;
03304   }
03305 
03306 }
03307 
03308 
03309 
03310 /**
03311   * @brief  Initialize the HASH peripheral in HMAC mode then initiate the required
03312   *         DMA transfers to feed the key and the input buffer to the Peripheral.
03313   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
03314   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
03315   * @note   In case of multi-buffer HMAC processing, the input buffer size (in bytes) must
03316   *         be a multiple of 4 otherwise, the HASH digest computation is corrupted.
03317   *         Only the length of the last buffer of the thread doesn't have to be a
03318   *         multiple of 4.
03319   * @param  hhash HASH handle.
03320   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
03321   * @param  Size length of the input buffer in bytes.
03322   * @param  Algorithm HASH algorithm.
03323   * @retval HAL status
03324   */
03325 HAL_StatusTypeDef HMAC_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm)
03326 {
03327   uint32_t inputaddr;
03328   uint32_t inputSize;
03329   HAL_StatusTypeDef status ;
03330   HAL_HASH_StateTypeDef State_tmp = hhash->State;
03331   /* Make sure the input buffer size (in bytes) is a multiple of 4 when digest calculation
03332      is disabled (multi-buffer HMAC processing, MDMAT bit to be set) */
03333   assert_param(IS_HMAC_DMA_MULTIBUFFER_SIZE(hhash, Size));
03334   /* If State is ready or suspended, start or resume DMA-based HASH processing */
03335   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
03336   {
03337     /* Check input parameters */
03338     if ((pInBuffer == NULL) || (Size == 0U) || (hhash->Init.pKey == NULL) || (hhash->Init.KeySize == 0U) ||
03339         /* Check phase coherency. Phase must be
03340             either READY (fresh start)
03341             or one of HMAC PROCESS steps (multi-buffer HASH management) */
03342         ((hhash->Phase != HAL_HASH_PHASE_READY) && (!(IS_HMAC_PROCESSING(hhash)))))
03343     {
03344       hhash->State = HAL_HASH_STATE_READY;
03345       return  HAL_ERROR;
03346     }
03347 
03348 
03349     /* Process Locked */
03350     __HAL_LOCK(hhash);
03351 
03352     /* If not a case of resumption after suspension */
03353     if (hhash->State == HAL_HASH_STATE_READY)
03354     {
03355       /* Check whether or not initialization phase has already be performed */
03356       if (hhash->Phase == HAL_HASH_PHASE_READY)
03357       {
03358         /* Change the HASH state */
03359         hhash->State = HAL_HASH_STATE_BUSY;
03360         /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits.
03361            At the same time, ensure MDMAT bit is cleared. */
03362         if (hhash->Init.KeySize > 64U)
03363         {
03364           MODIFY_REG(HASH->CR, HASH_CR_MDMAT | HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
03365                      Algorithm | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT);
03366         }
03367         else
03368         {
03369           MODIFY_REG(HASH->CR, HASH_CR_MDMAT | HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
03370                      Algorithm | HASH_ALGOMODE_HMAC | HASH_CR_INIT);
03371         }
03372         /* Store input aparameters in handle fields to manage steps transition
03373            or possible HMAC suspension/resumption */
03374         hhash->HashInCount = hhash->Init.KeySize;   /* Initial size for first DMA transfer (key size)      */
03375         hhash->pHashKeyBuffPtr = hhash->Init.pKey;  /* Key address                                         */
03376         hhash->pHashInBuffPtr  = hhash->Init.pKey ; /* First address passed to DMA (key address at Step 1) */
03377         hhash->pHashMsgBuffPtr = pInBuffer;         /* Input data address                                  */
03378         hhash->HashBuffSize = Size;                 /* input data size (in bytes)                          */
03379 
03380         /* Set DMA input parameters */
03381         inputaddr = (uint32_t)(hhash->Init.pKey);   /* Address passed to DMA (start by entering Key message) */
03382         inputSize = hhash->Init.KeySize;            /* Size for first DMA transfer (in bytes) */
03383 
03384         /* Configure the number of valid bits in last word of the key */
03385         __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
03386 
03387         /* Set the phase to Step 1 */
03388         hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_1;
03389 
03390       }
03391       else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)
03392       {
03393         /* Process a new input data message in case of multi-buffer HMAC processing
03394           (this is not a resumption case) */
03395 
03396         /* Change the HASH state */
03397         hhash->State = HAL_HASH_STATE_BUSY;
03398 
03399         /* Save input parameters to be able to manage possible suspension/resumption */
03400         hhash->HashInCount = Size;                /* Input message address       */
03401         hhash->pHashInBuffPtr = pInBuffer;        /* Input message size in bytes */
03402 
03403         /* Set DMA input parameters */
03404         inputaddr = (uint32_t)pInBuffer;           /* Input message address       */
03405         inputSize = Size;                          /* Input message size in bytes */
03406 
03407         if (hhash->DigestCalculationDisable == RESET)
03408         {
03409           /* This means this is the last buffer of the multi-buffer sequence: DCAL needs to be set. */
03410           __HAL_HASH_RESET_MDMAT();
03411           __HAL_HASH_SET_NBVALIDBITS(inputSize);
03412         }
03413       }
03414       else
03415       {
03416         /* Phase not aligned with handle READY state */
03417         __HAL_UNLOCK(hhash);
03418         /* Return function status */
03419         return HAL_ERROR;
03420       }
03421     }
03422     else
03423     {
03424       /* Resumption case (phase may be Step 1, 2 or 3) */
03425 
03426       /* Change the HASH state */
03427       hhash->State = HAL_HASH_STATE_BUSY;
03428 
03429       /* Set DMA input parameters at resumption location;
03430          inputaddr and inputSize are not set to the API input parameters
03431          but to those saved beforehand by HAL_HASH_DMAFeed_ProcessSuspend() when the
03432          processing was suspended. */
03433       inputaddr = (uint32_t)(hhash->pHashInBuffPtr);  /* Input message address       */
03434       inputSize = hhash->HashInCount;                 /* Input message size in bytes */
03435     }
03436 
03437 
03438     /* Set the HASH DMA transfer complete callback */
03439     hhash->hdmain->XferCpltCallback = HASH_DMAXferCplt;
03440     /* Set the DMA error callback */
03441     hhash->hdmain->XferErrorCallback = HASH_DMAError;
03442 
03443     /* Store number of words already pushed to manage proper DMA processing suspension */
03444     hhash->NbWordsAlreadyPushed = HASH_NBW_PUSHED();
03445 
03446     /* Enable the DMA In DMA channel */
03447     status = HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN,  \
03448                               (((inputSize % 4U) != 0U) ? ((inputSize + (4U - (inputSize % 4U))) / 4U) \
03449                               : (inputSize / 4U)));
03450 
03451     /* Enable DMA requests */
03452     SET_BIT(HASH->CR, HASH_CR_DMAE);
03453 
03454     /* Process Unlocked */
03455     __HAL_UNLOCK(hhash);
03456 
03457     /* Return function status */
03458     if (status != HAL_OK)
03459     {
03460       /* Update HASH state machine to error */
03461       hhash->State = HAL_HASH_STATE_ERROR;
03462     }
03463 
03464     /* Return function status */
03465     return status;
03466   }
03467   else
03468   {
03469     return HAL_BUSY;
03470   }
03471 }
03472 /**
03473   * @}
03474   */
03475 
03476 #endif /* HAL_HASH_MODULE_ENABLED */
03477 
03478 /**
03479   * @}
03480   */
03481 #endif /*  HASH*/
03482 /**
03483   * @}
03484   */
03485