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