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