STM32F439xx HAL User Manual
stm32f4xx_hal_hash_ex.c
Go to the documentation of this file.
00001 /**
00002   ******************************************************************************
00003   * @file    stm32f4xx_hal_hash_ex.c
00004   * @author  MCD Application Team
00005   * @brief   HASH HAL Extension module driver.
00006   *          This file provides firmware functions to manage the following 
00007   *          functionalities of HASH peripheral:
00008   *           + Extended HASH processing functions based on SHA224 Algorithm
00009   *           + Extended HASH processing functions based on SHA256 Algorithm
00010   *         
00011   @verbatim
00012   ==============================================================================
00013                      ##### How to use this driver #####
00014   ==============================================================================
00015     [..]
00016     The HASH HAL driver can be used as follows:
00017     (#)Initialize the HASH low level resources by implementing the HAL_HASH_MspInit():
00018         (##) Enable the HASH interface clock using __HAL_RCC_HASH_CLK_ENABLE()
00019         (##) In case of using processing APIs based on interrupts (e.g. HAL_HMACEx_SHA224_Start())
00020             (+++) Configure the HASH interrupt priority using HAL_NVIC_SetPriority()
00021             (+++) Enable the HASH IRQ handler using HAL_NVIC_EnableIRQ()
00022             (+++) In HASH IRQ handler, call HAL_HASH_IRQHandler()
00023         (##) In case of using DMA to control data transfer (e.g. HAL_HMACEx_SH224_Start_DMA())
00024             (+++) Enable the DMAx interface clock using __DMAx_CLK_ENABLE()
00025             (+++) Configure and enable one DMA stream one for managing data transfer from
00026                 memory to peripheral (input stream). Managing data transfer from
00027                 peripheral to memory can be performed only using CPU
00028             (+++) Associate the initialized DMA handle to the HASH DMA handle
00029                 using  __HAL_LINKDMA()
00030             (+++) Configure the priority and enable the NVIC for the transfer complete
00031                 interrupt on the DMA Stream: HAL_NVIC_SetPriority() and HAL_NVIC_EnableIRQ()
00032     (#)Initialize the HASH HAL using HAL_HASH_Init(). This function configures mainly:
00033         (##) The data type: 1-bit, 8-bit, 16-bit and 32-bit.
00034         (##) For HMAC, the encryption key.
00035         (##) For HMAC, the key size used for encryption.
00036     (#)Three processing functions are available:
00037         (##) Polling mode: processing APIs are blocking functions
00038              i.e. they process the data and wait till the digest computation is finished
00039              e.g. HAL_HASHEx_SHA224_Start()
00040         (##) Interrupt mode: encryption and decryption APIs are not blocking functions
00041                 i.e. they process the data under interrupt
00042                 e.g. HAL_HASHEx_SHA224_Start_IT()
00043         (##) DMA mode: processing APIs are not blocking functions and the CPU is
00044              not used for data transfer i.e. the data transfer is ensured by DMA
00045                 e.g. HAL_HASHEx_SHA224_Start_DMA()
00046     (#)When the processing function is called at first time after HAL_HASH_Init()
00047        the HASH peripheral is initialized and processes the buffer in input.
00048        After that, the digest computation is started.
00049        When processing multi-buffer use the accumulate function to write the
00050        data in the peripheral without starting the digest computation. In last 
00051        buffer use the start function to input the last buffer ans start the digest
00052        computation.
00053        (##) e.g. HAL_HASHEx_SHA224_Accumulate() : write 1st data buffer in the peripheral without starting the digest computation
00054        (##)  write (n-1)th data buffer in the peripheral without starting the digest computation
00055        (##)  HAL_HASHEx_SHA224_Start() : write (n)th data buffer in the peripheral and start the digest computation
00056     (#)In HMAC mode, there is no Accumulate API. Only Start API is available.
00057     (#)In case of using DMA, call the DMA start processing e.g. HAL_HASHEx_SHA224_Start_DMA().
00058        After that, call the finish function in order to get the digest value
00059        e.g. HAL_HASHEx_SHA224_Finish()
00060     (#)Call HAL_HASH_DeInit() to deinitialize the HASH peripheral.
00061 
00062   @endverbatim
00063   ******************************************************************************
00064   * @attention
00065   *
00066   * <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
00067   *
00068   * Redistribution and use in source and binary forms, with or without modification,
00069   * are permitted provided that the following conditions are met:
00070   *   1. Redistributions of source code must retain the above copyright notice,
00071   *      this list of conditions and the following disclaimer.
00072   *   2. Redistributions in binary form must reproduce the above copyright notice,
00073   *      this list of conditions and the following disclaimer in the documentation
00074   *      and/or other materials provided with the distribution.
00075   *   3. Neither the name of STMicroelectronics nor the names of its contributors
00076   *      may be used to endorse or promote products derived from this software
00077   *      without specific prior written permission.
00078   *
00079   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00080   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00081   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00082   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
00083   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00084   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00085   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00086   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00087   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00088   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00089   *
00090   ******************************************************************************
00091   */ 
00092 
00093 /* Includes ------------------------------------------------------------------*/
00094 #include "stm32f4xx_hal.h"
00095 
00096 /** @addtogroup STM32F4xx_HAL_Driver
00097   * @{
00098   */
00099 
00100 /** @defgroup HASHEx HASHEx
00101   * @brief HASH Extension HAL module driver.
00102   * @{
00103   */
00104 
00105 #ifdef HAL_HASH_MODULE_ENABLED
00106 
00107 #if defined(STM32F437xx) || defined(STM32F439xx) || defined(STM32F479xx)
00108 
00109 /* Private typedef -----------------------------------------------------------*/
00110 /* Private define ------------------------------------------------------------*/
00111 /* Private macro -------------------------------------------------------------*/
00112 /* Private variables ---------------------------------------------------------*/
00113 /* Private function prototypes -----------------------------------------------*/
00114 /** @addtogroup HASHEx_Private_Functions
00115   * @{
00116   */
00117 static void HASHEx_DMAXferCplt(DMA_HandleTypeDef *hdma);
00118 static void HASHEx_WriteData(uint8_t *pInBuffer, uint32_t Size);
00119 static void HASHEx_GetDigest(uint8_t *pMsgDigest, uint8_t Size);
00120 static void HASHEx_DMAError(DMA_HandleTypeDef *hdma);
00121 /**
00122   * @}
00123   */
00124   
00125 /* Private functions ---------------------------------------------------------*/
00126 
00127 /** @addtogroup HASHEx_Private_Functions
00128   * @{
00129   */
00130 
00131 /**
00132   * @brief  Writes the input buffer in data register.
00133   * @param  pInBuffer Pointer to input buffer
00134   * @param  Size The size of input buffer
00135   * @retval None
00136   */
00137 static void HASHEx_WriteData(uint8_t *pInBuffer, uint32_t Size)
00138 {
00139   uint32_t buffercounter;
00140   uint32_t inputaddr = (uint32_t) pInBuffer;
00141   
00142   for(buffercounter = 0U; buffercounter < Size; buffercounter+=4U)
00143   {
00144     HASH->DIN = *(uint32_t*)inputaddr;
00145     inputaddr+=4U;
00146   }
00147 }
00148 
00149 /**
00150   * @brief  Provides the message digest result.
00151   * @param  pMsgDigest Pointer to the message digest
00152   * @param  Size The size of the message digest in bytes
00153   * @retval None
00154   */
00155 static void HASHEx_GetDigest(uint8_t *pMsgDigest, uint8_t Size)
00156 {
00157   uint32_t msgdigest = (uint32_t)pMsgDigest;
00158   
00159   switch(Size)
00160   {
00161   case 16U:
00162     /* Read the message digest */
00163     *(uint32_t*)(msgdigest) = __REV(HASH->HR[0U]);
00164     msgdigest+=4U;
00165     *(uint32_t*)(msgdigest) = __REV(HASH->HR[1U]);
00166     msgdigest+=4U;
00167     *(uint32_t*)(msgdigest) = __REV(HASH->HR[2U]);
00168     msgdigest+=4U;
00169     *(uint32_t*)(msgdigest) = __REV(HASH->HR[3U]);
00170     break;
00171   case 20U:
00172     /* Read the message digest */
00173     *(uint32_t*)(msgdigest) = __REV(HASH->HR[0U]);
00174     msgdigest+=4U;
00175     *(uint32_t*)(msgdigest) = __REV(HASH->HR[1U]);
00176     msgdigest+=4U;
00177     *(uint32_t*)(msgdigest) = __REV(HASH->HR[2U]);
00178     msgdigest+=4U;
00179     *(uint32_t*)(msgdigest) = __REV(HASH->HR[3U]);
00180     msgdigest+=4U;
00181     *(uint32_t*)(msgdigest) = __REV(HASH->HR[4U]);
00182     break;
00183   case 28U:
00184     /* Read the message digest */
00185     *(uint32_t*)(msgdigest) = __REV(HASH->HR[0U]);
00186     msgdigest+=4U;
00187     *(uint32_t*)(msgdigest) = __REV(HASH->HR[1U]);
00188     msgdigest+=4U;
00189     *(uint32_t*)(msgdigest) = __REV(HASH->HR[2U]);
00190     msgdigest+=4U;
00191     *(uint32_t*)(msgdigest) = __REV(HASH->HR[3U]);
00192     msgdigest+=4U;
00193     *(uint32_t*)(msgdigest) = __REV(HASH->HR[4U]);
00194     msgdigest+=4U;
00195     *(uint32_t*)(msgdigest) = __REV(HASH_DIGEST->HR[5U]);
00196     msgdigest+=4U;
00197     *(uint32_t*)(msgdigest) = __REV(HASH_DIGEST->HR[6U]);
00198     break;
00199   case 32U:
00200     /* Read the message digest */
00201     *(uint32_t*)(msgdigest) = __REV(HASH->HR[0U]);
00202     msgdigest+=4U;
00203     *(uint32_t*)(msgdigest) = __REV(HASH->HR[1U]);
00204     msgdigest+=4U;
00205     *(uint32_t*)(msgdigest) = __REV(HASH->HR[2U]);
00206     msgdigest+=4U;
00207     *(uint32_t*)(msgdigest) = __REV(HASH->HR[3U]);
00208     msgdigest+=4U;
00209     *(uint32_t*)(msgdigest) = __REV(HASH->HR[4U]);
00210     msgdigest+=4U;
00211     *(uint32_t*)(msgdigest) = __REV(HASH_DIGEST->HR[5U]);
00212     msgdigest+=4U;
00213     *(uint32_t*)(msgdigest) = __REV(HASH_DIGEST->HR[6U]);
00214     msgdigest+=4U;
00215     *(uint32_t*)(msgdigest) = __REV(HASH_DIGEST->HR[7U]);
00216     break;
00217   default:
00218     break;
00219   }
00220 }
00221 
00222 /**
00223   * @brief  DMA HASH Input Data complete callback. 
00224   * @param  hdma DMA handle
00225   * @retval None
00226   */
00227 static void HASHEx_DMAXferCplt(DMA_HandleTypeDef *hdma)
00228 {
00229   HASH_HandleTypeDef* hhash = ( HASH_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
00230   uint32_t inputaddr = 0U;
00231   uint32_t buffersize = 0U;
00232   
00233   if((HASH->CR & HASH_CR_MODE) != HASH_CR_MODE)
00234   {
00235     /* Disable the DMA transfer */
00236     HASH->CR &= (uint32_t)(~HASH_CR_DMAE);
00237     
00238     /* Change HASH peripheral state */
00239     hhash->State = HAL_HASH_STATE_READY;
00240     
00241     /* Call Input data transfer complete callback */
00242     HAL_HASH_InCpltCallback(hhash);
00243   }
00244   else
00245   {
00246     /* Increment Interrupt counter */
00247     hhash->HashInCount++;
00248     /* Disable the DMA transfer before starting the next transfer */
00249     HASH->CR &= (uint32_t)(~HASH_CR_DMAE);
00250     
00251     if(hhash->HashInCount <= 2U)
00252     {
00253       /* In case HashInCount = 1, set the DMA to transfer data to HASH DIN register */
00254       if(hhash->HashInCount == 1U)
00255       {
00256         inputaddr = (uint32_t)hhash->pHashInBuffPtr;
00257         buffersize = hhash->HashBuffSize;
00258       }
00259       /* In case HashInCount = 2, set the DMA to transfer key to HASH DIN register */
00260       else if(hhash->HashInCount == 2U)
00261       {
00262         inputaddr = (uint32_t)hhash->Init.pKey;
00263         buffersize = hhash->Init.KeySize;
00264       }
00265       /* Configure the number of valid bits in last word of the message */
00266       MODIFY_REG(HASH->STR, HASH_STR_NBLW, 8U * (buffersize % 4U));
00267             
00268       /* Set the HASH DMA transfer complete */
00269       hhash->hdmain->XferCpltCallback = HASHEx_DMAXferCplt;
00270       
00271       /* Enable the DMA In DMA Stream */
00272       HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, (buffersize%4U ? (buffersize+3U)/4U:buffersize/4U));
00273       
00274       /* Enable DMA requests */
00275       HASH->CR |= (HASH_CR_DMAE);
00276     }
00277     else
00278     {
00279       /* Disable the DMA transfer */
00280       HASH->CR &= (uint32_t)(~HASH_CR_DMAE);
00281       
00282       /* Reset the InCount */
00283       hhash->HashInCount = 0U;
00284       
00285       /* Change HASH peripheral state */
00286       hhash->State = HAL_HASH_STATE_READY;
00287       
00288       /* Call Input data transfer complete callback */
00289       HAL_HASH_InCpltCallback(hhash);
00290     }
00291   }
00292 }
00293 
00294 /**
00295   * @brief  DMA HASH communication error callback. 
00296   * @param  hdma DMA handle
00297   * @retval None
00298   */
00299 static void HASHEx_DMAError(DMA_HandleTypeDef *hdma)
00300 {
00301   HASH_HandleTypeDef* hhash = ( HASH_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
00302   hhash->State= HAL_HASH_STATE_READY;
00303   HAL_HASH_ErrorCallback(hhash);
00304 }
00305 
00306  /**
00307   * @}
00308   */
00309   
00310 /* Exported functions --------------------------------------------------------*/
00311 /** @addtogroup HASHEx_Exported_Functions
00312   * @{
00313   */
00314   
00315 /** @defgroup  HASHEx_Group1 HASH processing functions  
00316  *  @brief   processing functions using polling mode 
00317  *
00318 @verbatim   
00319  ===============================================================================
00320               ##### HASH processing using polling mode functions #####
00321  ===============================================================================  
00322     [..]  This section provides functions allowing to calculate in polling mode
00323           the hash value using one of the following algorithms:
00324       (+) SHA224
00325       (+) SHA256
00326 
00327 @endverbatim
00328   * @{
00329   */
00330 
00331 /**
00332   * @brief  Initializes the HASH peripheral in SHA224 mode
00333   *         then processes pInBuffer. The digest is available in pOutBuffer
00334   * @param  hhash pointer to a HASH_HandleTypeDef structure that contains
00335   *         the configuration information for HASH module
00336   * @param  pInBuffer Pointer to the input buffer (buffer to be hashed).
00337   * @param  Size Length of the input buffer in bytes.
00338   *          If the Size is not multiple of 64 bytes, the padding is managed by hardware.
00339   * @param  pOutBuffer Pointer to the computed digest. Its size must be 28 bytes.
00340   * @param  Timeout Specify Timeout value   
00341   * @retval HAL status
00342   */
00343 HAL_StatusTypeDef HAL_HASHEx_SHA224_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout)
00344 {
00345   uint32_t tickstart = 0U;   
00346   
00347   /* Process Locked */
00348   __HAL_LOCK(hhash);
00349   
00350   /* Change the HASH state */
00351   hhash->State = HAL_HASH_STATE_BUSY;
00352   
00353   /* Check if initialization phase has already been performed */
00354   if(hhash->Phase == HAL_HASH_PHASE_READY)
00355   {
00356     /* Select the SHA224 mode and reset the HASH processor core, so that the HASH will be ready to compute 
00357        the message digest of a new message */
00358     HASH->CR |= HASH_ALGOSELECTION_SHA224 | HASH_CR_INIT;
00359   }
00360   
00361   /* Set the phase */
00362   hhash->Phase = HAL_HASH_PHASE_PROCESS;
00363   
00364   /* Configure the number of valid bits in last word of the message */
00365   __HAL_HASH_SET_NBVALIDBITS(Size);
00366   
00367   /* Write input buffer in data register */
00368   HASHEx_WriteData(pInBuffer, Size);
00369   
00370   /* Start the digest calculation */
00371   __HAL_HASH_START_DIGEST();
00372   
00373   /* Get tick */
00374   tickstart = HAL_GetTick();
00375   
00376   while((HASH->SR & HASH_FLAG_BUSY) == HASH_FLAG_BUSY)
00377   {
00378     /* Check for the Timeout */
00379     if(Timeout != HAL_MAX_DELAY)
00380     {
00381       if((Timeout == 0U)||((HAL_GetTick() - tickstart ) > Timeout))
00382       {
00383         /* Change state */
00384         hhash->State = HAL_HASH_STATE_TIMEOUT;
00385         
00386         /* Process Unlocked */          
00387         __HAL_UNLOCK(hhash);
00388         
00389         return HAL_TIMEOUT;
00390       }
00391     }
00392   }
00393   
00394   /* Read the message digest */
00395   HASHEx_GetDigest(pOutBuffer, 28U);
00396   
00397   /* Change the HASH state */
00398   hhash->State = HAL_HASH_STATE_READY;
00399   
00400   /* Process Unlocked */
00401   __HAL_UNLOCK(hhash);
00402   
00403   /* Return function status */
00404   return HAL_OK;
00405 }
00406 
00407 /**
00408   * @brief  Initializes the HASH peripheral in SHA256 mode then processes pInBuffer.
00409             The digest is available in pOutBuffer.
00410   * @param  hhash pointer to a HASH_HandleTypeDef structure that contains
00411   *         the configuration information for HASH module
00412   * @param  pInBuffer Pointer to the input buffer (buffer to be hashed). 
00413   * @param  Size Length of the input buffer in bytes.
00414   *          If the Size is not multiple of 64 bytes, the padding is managed by hardware.
00415   * @param  pOutBuffer Pointer to the computed digest. Its size must be 32 bytes.
00416   * @param  Timeout Specify Timeout value   
00417   * @retval HAL status
00418   */
00419 HAL_StatusTypeDef HAL_HASHEx_SHA256_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout)
00420 {
00421   uint32_t tickstart = 0U;   
00422   
00423   /* Process Locked */
00424   __HAL_LOCK(hhash);
00425   
00426   /* Change the HASH state */
00427   hhash->State = HAL_HASH_STATE_BUSY;
00428   
00429   /* Check if initialization phase has already been performed */
00430   if(hhash->Phase == HAL_HASH_PHASE_READY)
00431   {
00432     /* Select the SHA256 mode and reset the HASH processor core, so that the HASH will be ready to compute 
00433        the message digest of a new message */
00434     HASH->CR |= HASH_ALGOSELECTION_SHA256 | HASH_CR_INIT;
00435   }
00436   
00437   /* Set the phase */
00438   hhash->Phase = HAL_HASH_PHASE_PROCESS;
00439   
00440   /* Configure the number of valid bits in last word of the message */
00441   __HAL_HASH_SET_NBVALIDBITS(Size);
00442   
00443   /* Write input buffer in data register */
00444   HASHEx_WriteData(pInBuffer, Size);
00445   
00446   /* Start the digest calculation */
00447   __HAL_HASH_START_DIGEST();
00448   
00449   /* Get tick */
00450   tickstart = HAL_GetTick();
00451   
00452   while((HASH->SR & HASH_FLAG_BUSY) == HASH_FLAG_BUSY)
00453   {
00454     /* Check for the Timeout */
00455     if(Timeout != HAL_MAX_DELAY)
00456     {
00457       if((Timeout == 0U)||((HAL_GetTick() - tickstart ) > Timeout))
00458       {
00459         /* Change state */
00460         hhash->State = HAL_HASH_STATE_TIMEOUT;
00461         
00462         /* Process Unlocked */          
00463         __HAL_UNLOCK(hhash);
00464         
00465         return HAL_TIMEOUT;
00466       }
00467     }
00468   }
00469   
00470   /* Read the message digest */
00471   HASHEx_GetDigest(pOutBuffer, 32U);
00472   
00473   /* Change the HASH state */
00474   hhash->State = HAL_HASH_STATE_READY;
00475 
00476   /* Process Unlocked */
00477   __HAL_UNLOCK(hhash);  
00478   
00479   /* Return function status */
00480   return HAL_OK;
00481 }
00482 
00483 
00484 /**
00485   * @brief  Initializes the HASH peripheral in SHA224 mode
00486   *         then processes pInBuffer. The digest is available in pOutBuffer
00487   * @param  hhash pointer to a HASH_HandleTypeDef structure that contains
00488   *         the configuration information for HASH module
00489   * @param  pInBuffer Pointer to the input buffer (buffer to be hashed).
00490   * @param  Size Length of the input buffer in bytes.
00491   *          If the Size is not multiple of 64 bytes, the padding is managed by hardware.
00492   * @retval HAL status
00493   */
00494 HAL_StatusTypeDef HAL_HASHEx_SHA224_Accumulate(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
00495 {
00496   /* Process Locked */
00497   __HAL_LOCK(hhash);
00498   
00499   /* Change the HASH state */
00500   hhash->State = HAL_HASH_STATE_BUSY;
00501   
00502   /* Check if initialization phase has already been performed */
00503   if(hhash->Phase == HAL_HASH_PHASE_READY)
00504   {
00505     /* Select the SHA224 mode and reset the HASH processor core, so that the HASH will be ready to compute 
00506        the message digest of a new message */
00507     HASH->CR |= HASH_ALGOSELECTION_SHA224 | HASH_CR_INIT;
00508   }
00509   
00510   /* Set the phase */
00511   hhash->Phase = HAL_HASH_PHASE_PROCESS;
00512   
00513   /* Configure the number of valid bits in last word of the message */
00514   __HAL_HASH_SET_NBVALIDBITS(Size);
00515   
00516   /* Write input buffer in data register */
00517   HASHEx_WriteData(pInBuffer, Size);
00518   
00519   /* Change the HASH state */
00520   hhash->State = HAL_HASH_STATE_READY;
00521   
00522   /* Process Unlocked */
00523   __HAL_UNLOCK(hhash);
00524   
00525   /* Return function status */
00526   return HAL_OK;
00527 }
00528 
00529 
00530 /**
00531   * @brief  Initializes the HASH peripheral in SHA256 mode then processes pInBuffer.
00532             The digest is available in pOutBuffer.
00533   * @param  hhash pointer to a HASH_HandleTypeDef structure that contains
00534   *         the configuration information for HASH module
00535   * @param  pInBuffer Pointer to the input buffer (buffer to be hashed).
00536   * @param  Size Length of the input buffer in bytes.
00537   *          If the Size is not multiple of 64 bytes, the padding is managed by hardware.
00538   * @retval HAL status
00539   */
00540 HAL_StatusTypeDef HAL_HASHEx_SHA256_Accumulate(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
00541 {
00542    /* Process Locked */
00543   __HAL_LOCK(hhash);
00544   
00545   /* Change the HASH state */
00546   hhash->State = HAL_HASH_STATE_BUSY;
00547   
00548   /* Check if initialization phase has already been performed */
00549   if(hhash->Phase == HAL_HASH_PHASE_READY)
00550   {
00551     /* Select the SHA256 mode and reset the HASH processor core, so that the HASH will be ready to compute 
00552        the message digest of a new message */
00553     HASH->CR |= HASH_ALGOSELECTION_SHA256 | HASH_CR_INIT;
00554   }
00555   
00556   /* Set the phase */
00557   hhash->Phase = HAL_HASH_PHASE_PROCESS;
00558   
00559   /* Configure the number of valid bits in last word of the message */
00560   __HAL_HASH_SET_NBVALIDBITS(Size);
00561   
00562   /* Write input buffer in data register */
00563   HASHEx_WriteData(pInBuffer, Size);
00564   
00565   /* Change the HASH state */
00566   hhash->State = HAL_HASH_STATE_READY;
00567   
00568   /* Process Unlocked */
00569   __HAL_UNLOCK(hhash);
00570   
00571   /* Return function status */
00572   return HAL_OK;
00573 }
00574 
00575 
00576 /**
00577   * @}
00578   */
00579 
00580 /** @defgroup HASHEx_Group2 HMAC processing functions using polling mode 
00581  *  @brief   HMAC processing functions using polling mode . 
00582  *
00583 @verbatim   
00584  ===============================================================================
00585             ##### HMAC processing using polling mode functions #####
00586  ===============================================================================  
00587     [..]  This section provides functions allowing to calculate in polling mode
00588           the HMAC value using one of the following algorithms:
00589       (+) SHA224
00590       (+) SHA256
00591 
00592 @endverbatim
00593   * @{
00594   */
00595 
00596 /**
00597   * @brief  Initializes the HASH peripheral in HMAC SHA224 mode
00598   *         then processes pInBuffer. The digest is available in pOutBuffer.
00599   * @param  hhash pointer to a HASH_HandleTypeDef structure that contains
00600   *         the configuration information for HASH module
00601   * @param  pInBuffer Pointer to the input buffer (buffer to be hashed). 
00602   * @param  Size Length of the input buffer in bytes.
00603   *          If the Size is not multiple of 64 bytes, the padding is managed by hardware.
00604   * @param  pOutBuffer Pointer to the computed digest. Its size must be 20 bytes.
00605   * @param  Timeout Timeout value 
00606   * @retval HAL status
00607   */
00608 HAL_StatusTypeDef HAL_HMACEx_SHA224_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout)
00609 {
00610   uint32_t tickstart = 0U;   
00611                                                   
00612    /* Process Locked */
00613   __HAL_LOCK(hhash);
00614   
00615   /* Change the HASH state */
00616   hhash->State = HAL_HASH_STATE_BUSY;
00617   
00618   /* Check if initialization phase has already been performed */
00619   if(hhash->Phase == HAL_HASH_PHASE_READY)
00620   {
00621     /* Check if key size is greater than 64 bytes */
00622     if(hhash->Init.KeySize > 64U)
00623     {
00624       /* Select the HMAC SHA224 mode */
00625       HASH->CR |= (HASH_ALGOSELECTION_SHA224 | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT);
00626     }
00627     else
00628     {
00629       /* Select the HMAC SHA224 mode */
00630       HASH->CR |= (HASH_ALGOSELECTION_SHA224 | HASH_ALGOMODE_HMAC | HASH_CR_INIT);
00631     }
00632   }
00633   
00634   /* Set the phase */
00635   hhash->Phase = HAL_HASH_PHASE_PROCESS;
00636   
00637   /************************** STEP 1 ******************************************/
00638   /* Configure the number of valid bits in last word of the message */
00639   __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
00640   
00641   /* Write input buffer in data register */
00642   HASHEx_WriteData(hhash->Init.pKey, hhash->Init.KeySize);
00643   
00644   /* Start the digest calculation */
00645   __HAL_HASH_START_DIGEST();
00646   
00647   /* Get tick */
00648   tickstart = HAL_GetTick();
00649   
00650   while((HASH->SR & HASH_FLAG_BUSY) == HASH_FLAG_BUSY)
00651   {
00652     /* Check for the Timeout */
00653     if(Timeout != HAL_MAX_DELAY)
00654     {
00655       if((Timeout == 0U)||((HAL_GetTick() - tickstart ) > Timeout))
00656       {
00657         /* Change state */
00658         hhash->State = HAL_HASH_STATE_TIMEOUT;
00659         
00660         /* Process Unlocked */          
00661         __HAL_UNLOCK(hhash);
00662         
00663         return HAL_TIMEOUT;
00664       }
00665     }
00666   }
00667   /************************** STEP 2 ******************************************/
00668   /* Configure the number of valid bits in last word of the message */
00669   __HAL_HASH_SET_NBVALIDBITS(Size);
00670   
00671   /* Write input buffer in data register */
00672   HASHEx_WriteData(pInBuffer, Size);
00673   
00674   /* Start the digest calculation */
00675   __HAL_HASH_START_DIGEST();
00676   
00677   /* Get tick */
00678   tickstart = HAL_GetTick();
00679   
00680   while((HASH->SR & HASH_FLAG_BUSY) == HASH_FLAG_BUSY)
00681   {
00682     /* Check for the Timeout */
00683     if(Timeout != HAL_MAX_DELAY)
00684     {
00685       if((HAL_GetTick() - tickstart ) > Timeout)
00686       {
00687         /* Change state */
00688         hhash->State = HAL_HASH_STATE_TIMEOUT;
00689         
00690         /* Process Unlocked */          
00691         __HAL_UNLOCK(hhash);
00692         
00693         return HAL_TIMEOUT;
00694       }
00695     }
00696   }
00697   /************************** STEP 3 ******************************************/
00698   /* Configure the number of valid bits in last word of the message */
00699   __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
00700   
00701   /* Write input buffer in data register */
00702   HASHEx_WriteData(hhash->Init.pKey, hhash->Init.KeySize);
00703   
00704   /* Start the digest calculation */
00705   __HAL_HASH_START_DIGEST();
00706   
00707   /* Get tick */
00708   tickstart = HAL_GetTick();
00709   
00710   while((HASH->SR & HASH_FLAG_BUSY) == HASH_FLAG_BUSY)
00711   {
00712     /* Check for the Timeout */
00713     if(Timeout != HAL_MAX_DELAY)
00714     {
00715       if((HAL_GetTick() - tickstart ) > Timeout)
00716       {
00717         /* Change state */
00718         hhash->State = HAL_HASH_STATE_TIMEOUT;
00719         
00720         /* Process Unlocked */          
00721         __HAL_UNLOCK(hhash);
00722         
00723         return HAL_TIMEOUT;
00724       }
00725     }
00726   }
00727   /* Read the message digest */
00728   HASHEx_GetDigest(pOutBuffer, 28U);
00729   
00730   /* Change the HASH state */
00731   hhash->State = HAL_HASH_STATE_READY;
00732   
00733   /* Process Unlocked */
00734   __HAL_UNLOCK(hhash);
00735   
00736   /* Return function status */
00737   return HAL_OK;
00738 }
00739 
00740 /**
00741   * @brief  Initializes the HASH peripheral in HMAC SHA256 mode
00742   *         then processes pInBuffer. The digest is available in pOutBuffer
00743   * @param  hhash pointer to a HASH_HandleTypeDef structure that contains
00744   *         the configuration information for HASH module
00745   * @param  pInBuffer Pointer to the input buffer (buffer to be hashed). 
00746   * @param  Size Length of the input buffer in bytes.
00747   *          If the Size is not multiple of 64 bytes, the padding is managed by hardware.
00748   * @param  pOutBuffer Pointer to the computed digest. Its size must be 20 bytes.
00749   * @param  Timeout Timeout value 
00750   * @retval HAL status
00751   */
00752 HAL_StatusTypeDef HAL_HMACEx_SHA256_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout)
00753 {
00754   uint32_t tickstart = 0U;   
00755   
00756   /* Process Locked */
00757   __HAL_LOCK(hhash);
00758   
00759   /* Change the HASH state */
00760   hhash->State = HAL_HASH_STATE_BUSY;
00761   
00762   /* Check if initialization phase has already been performed */
00763   if(hhash->Phase == HAL_HASH_PHASE_READY)
00764   {
00765     /* Check if key size is greater than 64 bytes */
00766     if(hhash->Init.KeySize > 64U)
00767     {
00768       /* Select the HMAC SHA256 mode */
00769       HASH->CR |= (HASH_ALGOSELECTION_SHA256 | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY);
00770     }
00771     else
00772     {
00773       /* Select the HMAC SHA256 mode */
00774       HASH->CR |= (HASH_ALGOSELECTION_SHA256 | HASH_ALGOMODE_HMAC);
00775     }
00776     /* Reset the HASH processor core, so that the HASH will be ready to compute 
00777        the message digest of a new message */
00778     HASH->CR |= HASH_CR_INIT;
00779   }
00780   
00781   /* Set the phase */
00782   hhash->Phase = HAL_HASH_PHASE_PROCESS;
00783   
00784   /************************** STEP 1 ******************************************/
00785   /* Configure the number of valid bits in last word of the message */
00786   __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
00787   
00788   /* Write input buffer in data register */
00789   HASHEx_WriteData(hhash->Init.pKey, hhash->Init.KeySize);
00790   
00791   /* Start the digest calculation */
00792   __HAL_HASH_START_DIGEST();
00793   
00794   /* Get tick */
00795   tickstart = HAL_GetTick();
00796   
00797   while((HASH->SR & HASH_FLAG_BUSY) == HASH_FLAG_BUSY)
00798   {
00799     /* Check for the Timeout */
00800     if(Timeout != HAL_MAX_DELAY)
00801     {
00802       if((Timeout == 0U)||((HAL_GetTick() - tickstart ) > Timeout))
00803       {
00804         /* Change state */
00805         hhash->State = HAL_HASH_STATE_TIMEOUT;
00806         
00807         /* Process Unlocked */          
00808         __HAL_UNLOCK(hhash);
00809         
00810         return HAL_TIMEOUT;
00811       }
00812     }
00813   }
00814   /************************** STEP 2 ******************************************/
00815   /* Configure the number of valid bits in last word of the message */
00816   __HAL_HASH_SET_NBVALIDBITS(Size);
00817   
00818   /* Write input buffer in data register */
00819   HASHEx_WriteData(pInBuffer, Size);
00820   
00821   /* Start the digest calculation */
00822   __HAL_HASH_START_DIGEST();
00823   
00824   /* Get tick */
00825   tickstart = HAL_GetTick();
00826   
00827   while((HASH->SR & HASH_FLAG_BUSY) == HASH_FLAG_BUSY)
00828   {
00829     /* Check for the Timeout */
00830     if(Timeout != HAL_MAX_DELAY)
00831     {
00832       if((HAL_GetTick() - tickstart ) > Timeout)
00833       {
00834         /* Change state */
00835         hhash->State = HAL_HASH_STATE_TIMEOUT;
00836         
00837         /* Process Unlocked */          
00838         __HAL_UNLOCK(hhash);
00839         
00840         return HAL_TIMEOUT;
00841       }
00842     }
00843   }
00844   /************************** STEP 3 ******************************************/
00845   /* Configure the number of valid bits in last word of the message */
00846   __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
00847   
00848   /* Write input buffer in data register */
00849   HASHEx_WriteData(hhash->Init.pKey, hhash->Init.KeySize);
00850   
00851   /* Start the digest calculation */
00852   __HAL_HASH_START_DIGEST();
00853   
00854   /* Get tick */
00855   tickstart = HAL_GetTick();
00856   
00857   while((HASH->SR & HASH_FLAG_BUSY) == HASH_FLAG_BUSY)
00858   {
00859     /* Check for the Timeout */
00860     if(Timeout != HAL_MAX_DELAY)
00861     {
00862       if((HAL_GetTick() - tickstart ) > Timeout)
00863       {
00864         /* Change state */
00865         hhash->State = HAL_HASH_STATE_TIMEOUT;
00866         
00867         /* Process Unlocked */          
00868         __HAL_UNLOCK(hhash);
00869         
00870         return HAL_TIMEOUT;
00871       }
00872     }
00873   }
00874   /* Read the message digest */
00875   HASHEx_GetDigest(pOutBuffer, 32U);
00876   
00877   /* Change the HASH state */
00878   hhash->State = HAL_HASH_STATE_READY;
00879   
00880    /* Process Unlocked */
00881   __HAL_UNLOCK(hhash);
00882   
00883   /* Return function status */
00884   return HAL_OK;
00885 }
00886 
00887 /**
00888   * @}
00889   */
00890 
00891 /** @defgroup HASHEx_Group3 HASH processing functions using interrupt mode
00892  *  @brief   processing functions using interrupt mode. 
00893  *
00894 @verbatim   
00895  ===============================================================================
00896               ##### HASH processing using interrupt functions #####
00897  ===============================================================================  
00898     [..]  This section provides functions allowing to calculate in interrupt mode
00899           the hash value using one of the following algorithms:
00900       (+) SHA224
00901       (+) SHA256
00902 
00903 @endverbatim
00904   * @{
00905   */
00906 
00907 /**
00908   * @brief  Initializes the HASH peripheral in SHA224 mode then processes pInBuffer.
00909   *         The digest is available in pOutBuffer.
00910   * @param  hhash pointer to a HASH_HandleTypeDef structure that contains
00911   *         the configuration information for HASH module
00912   * @param  pInBuffer Pointer to the input buffer (buffer to be hashed).
00913   * @param  Size Length of the input buffer in bytes.
00914   *          If the Size is not multiple of 64 bytes, the padding is managed by hardware.
00915   * @param  pOutBuffer Pointer to the computed digest. Its size must be 20 bytes.
00916   * @retval HAL status
00917   */
00918 HAL_StatusTypeDef HAL_HASHEx_SHA224_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer)
00919 {
00920   uint32_t inputaddr;
00921   uint32_t buffercounter;
00922   uint32_t inputcounter;
00923   
00924   /* Process Locked */
00925   __HAL_LOCK(hhash);
00926   
00927   if(hhash->State == HAL_HASH_STATE_READY)
00928   {
00929     /* Change the HASH state */
00930     hhash->State = HAL_HASH_STATE_BUSY;
00931     
00932     hhash->HashInCount = Size;
00933     hhash->pHashInBuffPtr = pInBuffer;
00934     hhash->pHashOutBuffPtr = pOutBuffer;
00935     
00936     /* Check if initialization phase has already been performed */
00937     if(hhash->Phase == HAL_HASH_PHASE_READY)
00938     {
00939       /* Select the SHA224 mode */
00940       HASH->CR |= HASH_ALGOSELECTION_SHA224;
00941       /* Reset the HASH processor core, so that the HASH will be ready to compute 
00942          the message digest of a new message */
00943       HASH->CR |= HASH_CR_INIT;
00944     }
00945     /* Reset interrupt counter */
00946     hhash->HashITCounter = 0U;
00947     
00948     /* Set the phase */
00949     hhash->Phase = HAL_HASH_PHASE_PROCESS;
00950     
00951     /* Process Unlocked */
00952     __HAL_UNLOCK(hhash);
00953     
00954     /* Enable Interrupts */
00955     HASH->IMR = (HASH_IT_DINI | HASH_IT_DCI);
00956     
00957     /* Return function status */
00958     return HAL_OK;
00959   }
00960   if(__HAL_HASH_GET_FLAG(HASH_FLAG_DCIS))
00961   {
00962     /* Read the message digest */
00963     HASHEx_GetDigest(hhash->pHashOutBuffPtr, 28U);
00964     if(hhash->HashInCount == 0U)
00965     {
00966       /* Disable Interrupts */
00967       HASH->IMR = 0U;
00968       /* Change the HASH state */
00969       hhash->State = HAL_HASH_STATE_READY;
00970       /* Call digest computation complete callback */
00971       HAL_HASH_DgstCpltCallback(hhash);
00972       
00973       /* Process Unlocked */
00974       __HAL_UNLOCK(hhash);
00975       
00976       /* Return function status */
00977       return HAL_OK;
00978     }
00979   }
00980   if(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))
00981   {
00982     if(hhash->HashInCount >= 68U)
00983     {
00984       inputaddr = (uint32_t)hhash->pHashInBuffPtr;
00985       /* Write the Input block in the Data IN register */
00986       for(buffercounter = 0U; buffercounter < 64U; buffercounter+=4U)
00987       {
00988         HASH->DIN = *(uint32_t*)inputaddr;
00989         inputaddr+=4U;
00990       }
00991       if(hhash->HashITCounter == 0U)
00992       {
00993         HASH->DIN = *(uint32_t*)inputaddr;
00994 
00995         if(hhash->HashInCount >= 68U)
00996         {
00997           /* Decrement buffer counter */
00998           hhash->HashInCount -= 68U;
00999           hhash->pHashInBuffPtr+= 68U;
01000         }
01001         else
01002         {
01003           hhash->HashInCount = 0U;
01004           hhash->pHashInBuffPtr+= hhash->HashInCount;
01005         }
01006         /* Set Interrupt counter */
01007         hhash->HashITCounter = 1U;
01008       }
01009       else
01010       {
01011         /* Decrement buffer counter */
01012         hhash->HashInCount -= 64U;
01013         hhash->pHashInBuffPtr+= 64U;
01014       }
01015     }
01016     else
01017     {
01018       /* Get the buffer address */
01019       inputaddr = (uint32_t)hhash->pHashInBuffPtr;
01020       /* Get the buffer counter */
01021       inputcounter = hhash->HashInCount;
01022       /* Disable Interrupts */
01023       HASH->IMR &= ~(HASH_IT_DINI);
01024       /* Configure the number of valid bits in last word of the message */
01025       __HAL_HASH_SET_NBVALIDBITS(inputcounter);
01026       
01027       if((inputcounter > 4U) && (inputcounter%4U))
01028       {
01029         inputcounter = (inputcounter+4U-inputcounter%4U);
01030       }
01031       else if ((inputcounter < 4U) && (inputcounter != 0U))
01032       {
01033         inputcounter = 4U;
01034       }
01035       /* Write the Input block in the Data IN register */
01036       for(buffercounter = 0U; buffercounter < inputcounter/4U; buffercounter++)
01037       {
01038         HASH->DIN = *(uint32_t*)inputaddr;
01039         inputaddr+=4U;
01040       }
01041       /* Start the digest calculation */
01042       __HAL_HASH_START_DIGEST();
01043       /* Reset buffer counter */
01044       hhash->HashInCount = 0U;
01045       /* Call Input data transfer complete callback */
01046       HAL_HASH_InCpltCallback(hhash);
01047     }
01048   }
01049   
01050   /* Process Unlocked */
01051   __HAL_UNLOCK(hhash);
01052   
01053   /* Return function status */
01054   return HAL_OK;
01055 }
01056 
01057 
01058 /**
01059   * @brief  Initializes the HASH peripheral in SHA256 mode then processes pInBuffer.
01060   *         The digest is available in pOutBuffer.
01061   * @param  hhash pointer to a HASH_HandleTypeDef structure that contains
01062   *         the configuration information for HASH module
01063   * @param  pInBuffer Pointer to the input buffer (buffer to be hashed).
01064   * @param  Size Length of the input buffer in bytes.
01065   *          If the Size is not multiple of 64 bytes, the padding is managed by hardware.
01066   * @param  pOutBuffer Pointer to the computed digest. Its size must be 20 bytes.
01067   * @retval HAL status
01068   */
01069 HAL_StatusTypeDef HAL_HASHEx_SHA256_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer)
01070 {
01071   uint32_t inputaddr;
01072   uint32_t buffercounter;
01073   uint32_t inputcounter;
01074   
01075   /* Process Locked */
01076   __HAL_LOCK(hhash);
01077   
01078   if(hhash->State == HAL_HASH_STATE_READY)
01079   {
01080     /* Change the HASH state */
01081     hhash->State = HAL_HASH_STATE_BUSY;
01082     
01083     hhash->HashInCount = Size;
01084     hhash->pHashInBuffPtr = pInBuffer;
01085     hhash->pHashOutBuffPtr = pOutBuffer;
01086     
01087     /* Check if initialization phase has already been performed */
01088     if(hhash->Phase == HAL_HASH_PHASE_READY)
01089     {
01090       /* Select the SHA256 mode */
01091       HASH->CR |= HASH_ALGOSELECTION_SHA256;
01092       /* Reset the HASH processor core, so that the HASH will be ready to compute 
01093          the message digest of a new message */
01094       HASH->CR |= HASH_CR_INIT;
01095     }
01096     /* Reset interrupt counter */
01097     hhash->HashITCounter = 0U;
01098     
01099     /* Set the phase */
01100     hhash->Phase = HAL_HASH_PHASE_PROCESS;
01101     
01102     /* Process Unlocked */
01103     __HAL_UNLOCK(hhash);
01104     
01105     /* Enable Interrupts */
01106     HASH->IMR = (HASH_IT_DINI | HASH_IT_DCI);
01107     
01108     /* Return function status */
01109     return HAL_OK;
01110   }
01111   if(__HAL_HASH_GET_FLAG(HASH_FLAG_DCIS))
01112   {
01113     /* Read the message digest */
01114     HASHEx_GetDigest(hhash->pHashOutBuffPtr, 32U);
01115     if(hhash->HashInCount == 0U)
01116     {
01117       /* Disable Interrupts */
01118       HASH->IMR = 0U;
01119       /* Change the HASH state */
01120       hhash->State = HAL_HASH_STATE_READY;
01121       /* Call digest computation complete callback */
01122       HAL_HASH_DgstCpltCallback(hhash);
01123       
01124       /* Process Unlocked */
01125       __HAL_UNLOCK(hhash);
01126       
01127       /* Return function status */
01128       return HAL_OK;
01129     }
01130   }
01131   if(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))
01132   {
01133     if(hhash->HashInCount >= 68U)
01134     {
01135       inputaddr = (uint32_t)hhash->pHashInBuffPtr;
01136       /* Write the Input block in the Data IN register */
01137       for(buffercounter = 0U; buffercounter < 64U; buffercounter+=4U)
01138       {
01139         HASH->DIN = *(uint32_t*)inputaddr;
01140         inputaddr+=4U;
01141       }
01142       if(hhash->HashITCounter == 0U)
01143       {
01144         HASH->DIN = *(uint32_t*)inputaddr;
01145 
01146         if(hhash->HashInCount >= 68U)
01147         {
01148           /* Decrement buffer counter */
01149           hhash->HashInCount -= 68U;
01150           hhash->pHashInBuffPtr+= 68U;
01151         }
01152         else
01153         {
01154           hhash->HashInCount = 0U;
01155           hhash->pHashInBuffPtr+= hhash->HashInCount;
01156         }
01157         /* Set Interrupt counter */
01158         hhash->HashITCounter = 1U;
01159       }
01160       else
01161       {
01162         /* Decrement buffer counter */
01163         hhash->HashInCount -= 64U;
01164         hhash->pHashInBuffPtr+= 64U;
01165       }
01166     }
01167     else
01168     {
01169       /* Get the buffer address */
01170       inputaddr = (uint32_t)hhash->pHashInBuffPtr;
01171       /* Get the buffer counter */
01172       inputcounter = hhash->HashInCount;
01173       /* Disable Interrupts */
01174       HASH->IMR &= ~(HASH_IT_DINI);
01175       /* Configure the number of valid bits in last word of the message */
01176       __HAL_HASH_SET_NBVALIDBITS(inputcounter);
01177       
01178       if((inputcounter > 4U) && (inputcounter%4U))
01179       {
01180         inputcounter = (inputcounter+4U-inputcounter%4U);
01181       }
01182       else if ((inputcounter < 4U) && (inputcounter != 0U))
01183       {
01184         inputcounter = 4U;
01185       }
01186       /* Write the Input block in the Data IN register */
01187       for(buffercounter = 0U; buffercounter < inputcounter/4U; buffercounter++)
01188       {
01189         HASH->DIN = *(uint32_t*)inputaddr;
01190         inputaddr+=4U;
01191       }
01192       /* Start the digest calculation */
01193       __HAL_HASH_START_DIGEST();
01194       /* Reset buffer counter */
01195       hhash->HashInCount = 0U;
01196       /* Call Input data transfer complete callback */
01197       HAL_HASH_InCpltCallback(hhash);
01198     }
01199   }
01200   
01201   /* Process Unlocked */
01202   __HAL_UNLOCK(hhash);
01203   
01204   /* Return function status */
01205   return HAL_OK;
01206 }
01207 
01208 /**
01209   * @brief This function handles HASH interrupt request.
01210   * @param  hhash pointer to a HASH_HandleTypeDef structure that contains
01211   *         the configuration information for HASH module
01212   * @retval None
01213   */
01214 void HAL_HASHEx_IRQHandler(HASH_HandleTypeDef *hhash)
01215 {
01216   switch(HASH->CR & HASH_CR_ALGO)
01217   {
01218     
01219     case HASH_ALGOSELECTION_SHA224:
01220        HAL_HASHEx_SHA224_Start_IT(hhash, NULL, 0U, NULL);
01221     break;
01222     
01223     case HASH_ALGOSELECTION_SHA256:
01224       HAL_HASHEx_SHA256_Start_IT(hhash, NULL, 0U, NULL);
01225     break;
01226     
01227     default:
01228     break;
01229   }
01230 }
01231 
01232 /**
01233   * @}
01234   */
01235 
01236 /** @defgroup HASHEx_Group4 HASH processing functions using DMA mode
01237  *  @brief   processing functions using DMA mode. 
01238  *
01239 @verbatim   
01240  ===============================================================================
01241                 ##### HASH processing using DMA functions #####
01242  ===============================================================================  
01243     [..]  This section provides functions allowing to calculate in DMA mode
01244           the hash value using one of the following algorithms:
01245       (+) SHA224
01246       (+) SHA256
01247 
01248 @endverbatim
01249   * @{
01250   */
01251 
01252 
01253 /**
01254   * @brief  Initializes the HASH peripheral in SHA224 mode then enables DMA to
01255             control data transfer. Use HAL_HASH_SHA224_Finish() to get the digest.
01256   * @param  hhash pointer to a HASH_HandleTypeDef structure that contains
01257   *         the configuration information for HASH module
01258   * @param  pInBuffer Pointer to the input buffer (buffer to be hashed).
01259   * @param  Size Length of the input buffer in bytes.
01260   *          If the Size is not multiple of 64 bytes, the padding is managed by hardware.
01261   * @retval HAL status
01262   */
01263 HAL_StatusTypeDef HAL_HASHEx_SHA224_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
01264 {
01265   uint32_t inputaddr  = (uint32_t)pInBuffer;
01266   
01267    /* Process Locked */
01268   __HAL_LOCK(hhash);
01269   
01270   /* Change the HASH state */
01271   hhash->State = HAL_HASH_STATE_BUSY;
01272   
01273   /* Check if initialization phase has already been performed */
01274   if(hhash->Phase == HAL_HASH_PHASE_READY)
01275   {
01276     /* Select the SHA224 mode and reset the HASH processor core, so that the HASH will be ready to compute 
01277        the message digest of a new message */
01278     HASH->CR |= HASH_ALGOSELECTION_SHA224 | HASH_CR_INIT;
01279   }
01280    
01281   /* Configure the number of valid bits in last word of the message */
01282   __HAL_HASH_SET_NBVALIDBITS(Size);
01283   
01284   /* Set the phase */
01285   hhash->Phase = HAL_HASH_PHASE_PROCESS;
01286     
01287   /* Set the HASH DMA transfer complete callback */
01288   hhash->hdmain->XferCpltCallback = HASHEx_DMAXferCplt;
01289   /* Set the DMA error callback */
01290   hhash->hdmain->XferErrorCallback = HASHEx_DMAError;
01291   
01292   /* Enable the DMA In DMA Stream */
01293   HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, (Size%4U ? (Size+3U)/4U:Size/4U));
01294   
01295   /* Enable DMA requests */
01296   HASH->CR |= (HASH_CR_DMAE);
01297   
01298    /* Process Unlocked */
01299   __HAL_UNLOCK(hhash);
01300   
01301   /* Return function status */
01302   return HAL_OK;
01303 }
01304 
01305 /**
01306   * @brief  Returns the computed digest in SHA224
01307   * @param  hhash pointer to a HASH_HandleTypeDef structure that contains
01308   *         the configuration information for HASH module
01309   * @param  pOutBuffer Pointer to the computed digest. Its size must be 28 bytes.
01310   * @param  Timeout Timeout value    
01311   * @retval HAL status
01312   */
01313 HAL_StatusTypeDef HAL_HASHEx_SHA224_Finish(HASH_HandleTypeDef *hhash, uint8_t* pOutBuffer, uint32_t Timeout)
01314 {
01315   uint32_t tickstart = 0U;   
01316   
01317   /* Process Locked */
01318   __HAL_LOCK(hhash);
01319   
01320   /* Change HASH peripheral state */
01321   hhash->State = HAL_HASH_STATE_BUSY;
01322   
01323   /* Get tick */
01324   tickstart = HAL_GetTick();
01325   
01326   while(HAL_IS_BIT_CLR(HASH->SR, HASH_FLAG_DCIS))
01327   {
01328     /* Check for the Timeout */
01329     if(Timeout != HAL_MAX_DELAY)
01330     {
01331       if((Timeout == 0U)||((HAL_GetTick() - tickstart ) > Timeout))
01332       {
01333         /* Change state */
01334         hhash->State = HAL_HASH_STATE_TIMEOUT;
01335         
01336         /* Process Unlocked */          
01337         __HAL_UNLOCK(hhash);
01338         
01339         return HAL_TIMEOUT;
01340       }
01341     }
01342   }
01343   
01344   /* Read the message digest */
01345   HASHEx_GetDigest(pOutBuffer, 28U);
01346       
01347   /* Change HASH peripheral state */
01348   hhash->State = HAL_HASH_STATE_READY;
01349   
01350    /* Process Unlocked */
01351   __HAL_UNLOCK(hhash);
01352   
01353   /* Return function status */
01354   return HAL_OK;
01355 }
01356 
01357 /**
01358   * @brief  Initializes the HASH peripheral in SHA256 mode then enables DMA to
01359             control data transfer. Use HAL_HASH_SHA256_Finish() to get the digest.
01360   * @param  hhash pointer to a HASH_HandleTypeDef structure that contains
01361   *         the configuration information for HASH module
01362   * @param  pInBuffer Pointer to the input buffer (buffer to be hashed).
01363   * @param  Size Length of the input buffer in bytes.
01364   *          If the Size is not multiple of 64 bytes, the padding is managed by hardware.
01365   * @retval HAL status
01366   */
01367 HAL_StatusTypeDef HAL_HASHEx_SHA256_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
01368 {
01369   uint32_t inputaddr  = (uint32_t)pInBuffer;
01370   
01371    /* Process Locked */
01372   __HAL_LOCK(hhash);
01373   
01374   /* Change the HASH state */
01375   hhash->State = HAL_HASH_STATE_BUSY;
01376   
01377   /* Check if initialization phase has already been performed */
01378   if(hhash->Phase == HAL_HASH_PHASE_READY)
01379   {
01380     /* Select the SHA256 mode and reset the HASH processor core, so that the HASH will be ready to compute 
01381        the message digest of a new message */
01382     HASH->CR |= HASH_ALGOSELECTION_SHA256 | HASH_CR_INIT;
01383   }
01384   
01385   /* Configure the number of valid bits in last word of the message */
01386   __HAL_HASH_SET_NBVALIDBITS(Size);
01387   
01388   /* Set the phase */
01389   hhash->Phase = HAL_HASH_PHASE_PROCESS;
01390     
01391   /* Set the HASH DMA transfer complete callback */
01392   hhash->hdmain->XferCpltCallback = HASHEx_DMAXferCplt;
01393   /* Set the DMA error callback */
01394   hhash->hdmain->XferErrorCallback = HASHEx_DMAError;
01395   
01396   /* Enable the DMA In DMA Stream */
01397   HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, (Size%4U ? (Size+3U)/4U:Size/4U));
01398   
01399   /* Enable DMA requests */
01400   HASH->CR |= (HASH_CR_DMAE);
01401   
01402    /* Process UnLock */
01403   __HAL_UNLOCK(hhash);
01404   
01405   /* Return function status */
01406   return HAL_OK;
01407 }
01408 
01409 /**
01410   * @brief  Returns the computed digest in SHA256.
01411   * @param  hhash pointer to a HASH_HandleTypeDef structure that contains
01412   *         the configuration information for HASH module
01413   * @param  pOutBuffer Pointer to the computed digest. Its size must be 32 bytes.
01414   * @param  Timeout Timeout value    
01415   * @retval HAL status
01416   */
01417 HAL_StatusTypeDef HAL_HASHEx_SHA256_Finish(HASH_HandleTypeDef *hhash, uint8_t* pOutBuffer, uint32_t Timeout)
01418 {
01419   uint32_t tickstart = 0U;   
01420   
01421    /* Process Locked */
01422   __HAL_LOCK(hhash);
01423   
01424   /* Change HASH peripheral state */
01425   hhash->State = HAL_HASH_STATE_BUSY;
01426   
01427   /* Get tick */
01428   tickstart = HAL_GetTick();
01429   
01430   while(HAL_IS_BIT_CLR(HASH->SR, HASH_FLAG_DCIS))
01431   {
01432     /* Check for the Timeout */
01433     if(Timeout != HAL_MAX_DELAY)
01434     {
01435       if((Timeout == 0U)||((HAL_GetTick() - tickstart ) > Timeout))
01436       {
01437         /* Change state */
01438         hhash->State = HAL_HASH_STATE_TIMEOUT;
01439         
01440         /* Process Unlocked */          
01441         __HAL_UNLOCK(hhash);
01442         
01443         return HAL_TIMEOUT;
01444       }
01445     }
01446   }
01447   
01448   /* Read the message digest */
01449   HASHEx_GetDigest(pOutBuffer, 32U);
01450   
01451   /* Change HASH peripheral state */
01452   hhash->State = HAL_HASH_STATE_READY;
01453   
01454    /* Process Unlocked */
01455   __HAL_UNLOCK(hhash);
01456   
01457   /* Return function status */
01458   return HAL_OK;
01459 }
01460 
01461 
01462 /**
01463   * @}
01464   */
01465 /** @defgroup HASHEx_Group5 HMAC processing functions using DMA mode 
01466  *  @brief   HMAC processing functions using DMA mode . 
01467  *
01468 @verbatim   
01469  ===============================================================================
01470                 ##### HMAC processing using DMA functions #####
01471  ===============================================================================  
01472     [..]  This section provides functions allowing to calculate in DMA mode
01473           the HMAC value using one of the following algorithms:
01474       (+) SHA224
01475       (+) SHA256
01476 
01477 @endverbatim
01478   * @{
01479   */
01480 
01481 /**
01482   * @brief  Initializes the HASH peripheral in HMAC SHA224 mode
01483   *         then enables DMA to control data transfer.
01484   * @param  hhash pointer to a HASH_HandleTypeDef structure that contains
01485   *         the configuration information for HASH module
01486   * @param  pInBuffer Pointer to the input buffer (buffer to be hashed).
01487   * @param  Size Length of the input buffer in bytes.
01488   *          If the Size is not multiple of 64 bytes, the padding is managed by hardware.
01489   * @retval HAL status
01490   */
01491 HAL_StatusTypeDef HAL_HMACEx_SHA224_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
01492 {
01493   uint32_t inputaddr;
01494   
01495   /* Process Locked */
01496   __HAL_LOCK(hhash);
01497   
01498   /* Change the HASH state */
01499   hhash->State = HAL_HASH_STATE_BUSY;
01500   
01501   /* Save buffer pointer and size in handle */
01502   hhash->pHashInBuffPtr = pInBuffer;
01503   hhash->HashBuffSize = Size;
01504   hhash->HashInCount = 0U;
01505   
01506   /* Check if initialization phase has already been performed */
01507   if(hhash->Phase == HAL_HASH_PHASE_READY)
01508   {
01509     /* Check if key size is greater than 64 bytes */
01510     if(hhash->Init.KeySize > 64U)
01511     {
01512       /* Select the HMAC SHA224 mode */
01513       HASH->CR |= (HASH_ALGOSELECTION_SHA224 | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT);
01514     }
01515     else
01516     {
01517       /* Select the HMAC SHA224 mode */
01518       HASH->CR |= (HASH_ALGOSELECTION_SHA224 | HASH_ALGOMODE_HMAC | HASH_CR_INIT);
01519     }
01520   }
01521   
01522   /* Set the phase */
01523   hhash->Phase = HAL_HASH_PHASE_PROCESS;
01524   
01525   /* Configure the number of valid bits in last word of the message */
01526   __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
01527   
01528   /* Get the key address */
01529   inputaddr = (uint32_t)(hhash->Init.pKey);
01530   
01531   /* Set the HASH DMA transfer complete callback */
01532   hhash->hdmain->XferCpltCallback = HASHEx_DMAXferCplt;
01533   /* Set the DMA error callback */
01534   hhash->hdmain->XferErrorCallback = HASHEx_DMAError;
01535   
01536   /* Enable the DMA In DMA Stream */
01537   HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, (hhash->Init.KeySize%4U ? (hhash->Init.KeySize+3U)/4U:hhash->Init.KeySize/4U));
01538   /* Enable DMA requests */
01539   HASH->CR |= (HASH_CR_DMAE);
01540   
01541   /* Process Unlocked */
01542   __HAL_UNLOCK(hhash);
01543   
01544   /* Return function status */
01545   return HAL_OK;
01546 }
01547 
01548 /**
01549   * @brief  Initializes the HASH peripheral in HMAC SHA256 mode
01550   *         then enables DMA to control data transfer.
01551   * @param  hhash pointer to a HASH_HandleTypeDef structure that contains
01552   *         the configuration information for HASH module
01553   * @param  pInBuffer Pointer to the input buffer (buffer to be hashed).
01554   * @param  Size Length of the input buffer in bytes.
01555   *          If the Size is not multiple of 64 bytes, the padding is managed by hardware.
01556   * @retval HAL status
01557   */
01558 HAL_StatusTypeDef HAL_HMACEx_SHA256_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
01559 {
01560   uint32_t inputaddr;
01561   
01562   /* Process Locked */
01563   __HAL_LOCK(hhash);
01564   
01565   /* Change the HASH state */
01566   hhash->State = HAL_HASH_STATE_BUSY;
01567   
01568   /* Save buffer pointer and size in handle */
01569   hhash->pHashInBuffPtr = pInBuffer;
01570   hhash->HashBuffSize = Size;
01571   hhash->HashInCount = 0U;
01572   
01573   /* Check if initialization phase has already been performed */
01574   if(hhash->Phase == HAL_HASH_PHASE_READY)
01575   {
01576     /* Check if key size is greater than 64 bytes */
01577     if(hhash->Init.KeySize > 64U)
01578     {
01579       /* Select the HMAC SHA256 mode */
01580       HASH->CR |= (HASH_ALGOSELECTION_SHA256 | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY);
01581     }
01582     else
01583     {
01584       /* Select the HMAC SHA256 mode */
01585       HASH->CR |= (HASH_ALGOSELECTION_SHA256 | HASH_ALGOMODE_HMAC);
01586     }
01587     /* Reset the HASH processor core, so that the HASH will be ready to compute 
01588        the message digest of a new message */
01589     HASH->CR |= HASH_CR_INIT;
01590   }
01591   
01592   /* Set the phase */
01593   hhash->Phase = HAL_HASH_PHASE_PROCESS;
01594   
01595   /* Configure the number of valid bits in last word of the message */
01596   __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
01597   
01598   /* Get the key address */
01599   inputaddr = (uint32_t)(hhash->Init.pKey);
01600   
01601   /* Set the HASH DMA transfer complete callback */
01602   hhash->hdmain->XferCpltCallback = HASHEx_DMAXferCplt;
01603   /* Set the DMA error callback */
01604   hhash->hdmain->XferErrorCallback = HASHEx_DMAError;
01605   
01606   /* Enable the DMA In DMA Stream */
01607   HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, (hhash->Init.KeySize%4U ? (hhash->Init.KeySize+3U)/4U:hhash->Init.KeySize/4U));
01608   /* Enable DMA requests */
01609   HASH->CR |= (HASH_CR_DMAE);
01610   
01611   /* Process Unlocked */
01612   __HAL_UNLOCK(hhash);
01613   
01614   /* Return function status */
01615   return HAL_OK;
01616 }
01617 
01618 /**
01619   * @}
01620   */
01621 
01622 /**
01623   * @}
01624   */
01625 #endif /* STM32F437xx || STM32F439xx || STM32F479xx */
01626 
01627 #endif /* HAL_HASH_MODULE_ENABLED */
01628 /**
01629   * @}
01630   */
01631 
01632 /**
01633   * @}
01634   */
01635 
01636 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/