| /** |
| ****************************************************************************** |
| * @file stm32f7xx_hal_hash.c |
| * @author MCD Application Team |
| * @brief HASH HAL module driver. |
| * This file provides firmware functions to manage the following |
| * functionalities of the HASH peripheral: |
| * + Initialization and de-initialization functions |
| * + HASH/HMAC Processing functions by algorithm using polling mode |
| * + HASH/HMAC functions by algorithm using interrupt mode |
| * + HASH/HMAC functions by algorithm using DMA mode |
| * + Peripheral State functions |
| * |
| @verbatim |
| ============================================================================== |
| ##### How to use this driver ##### |
| ============================================================================== |
| [..] |
| The HASH HAL driver can be used as follows: |
| (#)Initialize the HASH low level resources by implementing the HAL_HASH_MspInit(): |
| (##) Enable the HASH interface clock using __HAL_RCC_HASH_CLK_ENABLE() |
| (##) In case of using processing APIs based on interrupts (e.g. HAL_HMAC_SHA1_Start_IT()) |
| (+++) Configure the HASH interrupt priority using HAL_NVIC_SetPriority() |
| (+++) Enable the HASH IRQ handler using HAL_NVIC_EnableIRQ() |
| (+++) In HASH IRQ handler, call HAL_HASH_IRQHandler() |
| (##) In case of using DMA to control data transfer (e.g. HAL_HMAC_SHA1_Start_DMA()) |
| (+++) Enable the DMAx interface clock using __DMAx_CLK_ENABLE() |
| (+++) Configure and enable one DMA stream one for managing data transfer from |
| memory to peripheral (input stream). Managing data transfer from |
| peripheral to memory can be performed only using CPU |
| (+++) Associate the initialized DMA handle to the HASH DMA handle |
| using __HAL_LINKDMA() |
| (+++) Configure the priority and enable the NVIC for the transfer complete |
| interrupt on the DMA Stream using HAL_NVIC_SetPriority() and HAL_NVIC_EnableIRQ() |
| (#)Initialize the HASH HAL using HAL_HASH_Init(). This function configures mainly: |
| (##) The data type: 1-bit, 8-bit, 16-bit and 32-bit. |
| (##) For HMAC, the encryption key. |
| (##) For HMAC, the key size used for encryption. |
| (#)Three processing functions are available: |
| (##) Polling mode: processing APIs are blocking functions |
| i.e. they process the data and wait till the digest computation is finished |
| e.g. HAL_HASH_SHA1_Start() |
| (##) Interrupt mode: encryption and decryption APIs are not blocking functions |
| i.e. they process the data under interrupt |
| e.g. HAL_HASH_SHA1_Start_IT() |
| (##) DMA mode: processing APIs are not blocking functions and the CPU is |
| not used for data transfer i.e. the data transfer is ensured by DMA |
| e.g. HAL_HASH_SHA1_Start_DMA() |
| (#)When the processing function is called at first time after HAL_HASH_Init() |
| the HASH peripheral is initialized and processes the buffer in input. |
| After that, the digest computation is started. |
| When processing multi-buffer use the accumulate function to write the |
| data in the peripheral without starting the digest computation. In last |
| buffer use the start function to input the last buffer ans start the digest |
| computation. |
| (##) e.g. HAL_HASH_SHA1_Accumulate() : write 1st data buffer in the peripheral without starting the digest computation |
| (##) write (n-1)th data buffer in the peripheral without starting the digest computation |
| (##) HAL_HASH_SHA1_Start() : write (n)th data buffer in the peripheral and start the digest computation |
| (#)In HMAC mode, there is no Accumulate API. Only Start API is available. |
| (#)In case of using DMA, call the DMA start processing e.g. HAL_HASH_SHA1_Start_DMA(). |
| After that, call the finish function in order to get the digest value |
| e.g. HAL_HASH_SHA1_Finish() |
| (#)Call HAL_HASH_DeInit() to deinitialize the HASH peripheral. |
| |
| @endverbatim |
| ****************************************************************************** |
| * @attention |
| * |
| * <h2><center>© COPYRIGHT(c) 2017 STMicroelectronics</center></h2> |
| * |
| * Redistribution and use in source and binary forms, with or without modification, |
| * are permitted provided that the following conditions are met: |
| * 1. Redistributions of source code must retain the above copyright notice, |
| * this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright notice, |
| * this list of conditions and the following disclaimer in the documentation |
| * and/or other materials provided with the distribution. |
| * 3. Neither the name of STMicroelectronics nor the names of its contributors |
| * may be used to endorse or promote products derived from this software |
| * without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE |
| * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
| * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
| * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
| * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| * |
| ****************************************************************************** |
| */ |
| |
| /* Includes ------------------------------------------------------------------*/ |
| #include "stm32f7xx_hal.h" |
| |
| /** @addtogroup STM32F7xx_HAL_Driver |
| * @{ |
| */ |
| |
| #if defined (STM32F756xx) || defined (STM32F777xx) || defined (STM32F779xx) |
| |
| /** @defgroup HASH HASH |
| * @brief HASH HAL module driver. |
| * @{ |
| */ |
| #ifdef HAL_HASH_MODULE_ENABLED |
| |
| /* Private typedef -----------------------------------------------------------*/ |
| /* Private define ------------------------------------------------------------*/ |
| /* Private macro -------------------------------------------------------------*/ |
| /* Private variables ---------------------------------------------------------*/ |
| /* Private function prototypes -----------------------------------------------*/ |
| /** @defgroup HASH_Private_Functions HASH Private Functions |
| * @{ |
| */ |
| static void HASH_DMAXferCplt(DMA_HandleTypeDef *hdma); |
| static void HASH_DMAError(DMA_HandleTypeDef *hdma); |
| static void HASH_GetDigest(uint8_t *pMsgDigest, uint8_t Size); |
| static void HASH_WriteData(uint8_t *pInBuffer, uint32_t Size); |
| /** |
| * @} |
| */ |
| |
| /* Private functions ---------------------------------------------------------*/ |
| /** @addtogroup HASH_Private_Functions |
| * @{ |
| */ |
| |
| /** |
| * @brief DMA HASH Input Data complete callback. |
| * @param hdma DMA handle |
| * @retval None |
| */ |
| static void HASH_DMAXferCplt(DMA_HandleTypeDef *hdma) |
| { |
| HASH_HandleTypeDef* hhash = ( HASH_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; |
| uint32_t inputaddr = 0; |
| uint32_t buffersize = 0; |
| |
| if((HASH->CR & HASH_CR_MODE) != HASH_CR_MODE) |
| { |
| /* Disable the DMA transfer */ |
| HASH->CR &= (uint32_t)(~HASH_CR_DMAE); |
| |
| /* Change HASH peripheral state */ |
| hhash->State = HAL_HASH_STATE_READY; |
| |
| /* Call Input data transfer complete callback */ |
| HAL_HASH_InCpltCallback(hhash); |
| } |
| else |
| { |
| /* Increment Interrupt counter */ |
| hhash->HashInCount++; |
| /* Disable the DMA transfer before starting the next transfer */ |
| HASH->CR &= (uint32_t)(~HASH_CR_DMAE); |
| |
| if(hhash->HashInCount <= 2) |
| { |
| /* In case HashInCount = 1, set the DMA to transfer data to HASH DIN register */ |
| if(hhash->HashInCount == 1) |
| { |
| inputaddr = (uint32_t)hhash->pHashInBuffPtr; |
| buffersize = hhash->HashBuffSize; |
| } |
| /* In case HashInCount = 2, set the DMA to transfer key to HASH DIN register */ |
| else if(hhash->HashInCount == 2) |
| { |
| inputaddr = (uint32_t)hhash->Init.pKey; |
| buffersize = hhash->Init.KeySize; |
| } |
| /* Configure the number of valid bits in last word of the message */ |
| MODIFY_REG(HASH->STR, HASH_STR_NBLW, 8 * (buffersize % 4)); |
| |
| /* Set the HASH DMA transfer complete */ |
| hhash->hdmain->XferCpltCallback = HASH_DMAXferCplt; |
| |
| /* Enable the DMA In DMA Stream */ |
| HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, (buffersize%4 ? (buffersize+3)/4:buffersize/4)); |
| |
| /* Enable DMA requests */ |
| HASH->CR |= (HASH_CR_DMAE); |
| } |
| else |
| { |
| /* Disable the DMA transfer */ |
| HASH->CR &= (uint32_t)(~HASH_CR_DMAE); |
| |
| /* Reset the InCount */ |
| hhash->HashInCount = 0; |
| |
| /* Change HASH peripheral state */ |
| hhash->State = HAL_HASH_STATE_READY; |
| |
| /* Call Input data transfer complete callback */ |
| HAL_HASH_InCpltCallback(hhash); |
| } |
| } |
| } |
| |
| /** |
| * @brief DMA HASH communication error callback. |
| * @param hdma DMA handle |
| * @retval None |
| */ |
| static void HASH_DMAError(DMA_HandleTypeDef *hdma) |
| { |
| HASH_HandleTypeDef* hhash = ( HASH_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; |
| hhash->State= HAL_HASH_STATE_READY; |
| HAL_HASH_ErrorCallback(hhash); |
| } |
| |
| /** |
| * @brief Writes the input buffer in data register. |
| * @param pInBuffer Pointer to input buffer |
| * @param Size The size of input buffer |
| * @retval None |
| */ |
| static void HASH_WriteData(uint8_t *pInBuffer, uint32_t Size) |
| { |
| uint32_t buffercounter; |
| uint32_t inputaddr = (uint32_t) pInBuffer; |
| |
| for(buffercounter = 0; buffercounter < Size; buffercounter+=4) |
| { |
| HASH->DIN = *(uint32_t*)inputaddr; |
| inputaddr+=4; |
| } |
| } |
| |
| /** |
| * @brief Provides the message digest result. |
| * @param pMsgDigest Pointer to the message digest |
| * @param Size The size of the message digest in bytes |
| * @retval None |
| */ |
| static void HASH_GetDigest(uint8_t *pMsgDigest, uint8_t Size) |
| { |
| uint32_t msgdigest = (uint32_t)pMsgDigest; |
| |
| switch(Size) |
| { |
| case 16: |
| /* Read the message digest */ |
| *(uint32_t*)(msgdigest) = __REV(HASH->HR[0]); |
| msgdigest+=4; |
| *(uint32_t*)(msgdigest) = __REV(HASH->HR[1]); |
| msgdigest+=4; |
| *(uint32_t*)(msgdigest) = __REV(HASH->HR[2]); |
| msgdigest+=4; |
| *(uint32_t*)(msgdigest) = __REV(HASH->HR[3]); |
| break; |
| case 20: |
| /* Read the message digest */ |
| *(uint32_t*)(msgdigest) = __REV(HASH->HR[0]); |
| msgdigest+=4; |
| *(uint32_t*)(msgdigest) = __REV(HASH->HR[1]); |
| msgdigest+=4; |
| *(uint32_t*)(msgdigest) = __REV(HASH->HR[2]); |
| msgdigest+=4; |
| *(uint32_t*)(msgdigest) = __REV(HASH->HR[3]); |
| msgdigest+=4; |
| *(uint32_t*)(msgdigest) = __REV(HASH->HR[4]); |
| break; |
| case 28: |
| /* Read the message digest */ |
| *(uint32_t*)(msgdigest) = __REV(HASH->HR[0]); |
| msgdigest+=4; |
| *(uint32_t*)(msgdigest) = __REV(HASH->HR[1]); |
| msgdigest+=4; |
| *(uint32_t*)(msgdigest) = __REV(HASH->HR[2]); |
| msgdigest+=4; |
| *(uint32_t*)(msgdigest) = __REV(HASH->HR[3]); |
| msgdigest+=4; |
| *(uint32_t*)(msgdigest) = __REV(HASH->HR[4]); |
| msgdigest+=4; |
| *(uint32_t*)(msgdigest) = __REV(HASH_DIGEST->HR[5]); |
| msgdigest+=4; |
| *(uint32_t*)(msgdigest) = __REV(HASH_DIGEST->HR[6]); |
| break; |
| case 32: |
| /* Read the message digest */ |
| *(uint32_t*)(msgdigest) = __REV(HASH->HR[0]); |
| msgdigest+=4; |
| *(uint32_t*)(msgdigest) = __REV(HASH->HR[1]); |
| msgdigest+=4; |
| *(uint32_t*)(msgdigest) = __REV(HASH->HR[2]); |
| msgdigest+=4; |
| *(uint32_t*)(msgdigest) = __REV(HASH->HR[3]); |
| msgdigest+=4; |
| *(uint32_t*)(msgdigest) = __REV(HASH->HR[4]); |
| msgdigest+=4; |
| *(uint32_t*)(msgdigest) = __REV(HASH_DIGEST->HR[5]); |
| msgdigest+=4; |
| *(uint32_t*)(msgdigest) = __REV(HASH_DIGEST->HR[6]); |
| msgdigest+=4; |
| *(uint32_t*)(msgdigest) = __REV(HASH_DIGEST->HR[7]); |
| break; |
| default: |
| break; |
| } |
| } |
| |
| /** |
| * @} |
| */ |
| |
| /* Exported functions --------------------------------------------------------*/ |
| /** @addtogroup HASH_Exported_Functions |
| * @{ |
| */ |
| |
| |
| /** @addtogroup HASH_Exported_Functions_Group1 Initialization and de-initialization functions |
| * @brief Initialization and Configuration functions. |
| * |
| @verbatim |
| =============================================================================== |
| ##### Initialization and de-initialization functions ##### |
| =============================================================================== |
| [..] This section provides functions allowing to: |
| (+) Initialize the HASH according to the specified parameters |
| in the HASH_InitTypeDef and creates the associated handle. |
| (+) DeInitialize the HASH peripheral. |
| (+) Initialize the HASH MSP. |
| (+) DeInitialize HASH MSP. |
| |
| @endverbatim |
| * @{ |
| */ |
| |
| /** |
| * @brief Initializes the HASH according to the specified parameters in the |
| HASH_HandleTypeDef and creates the associated handle. |
| * @param hhash pointer to a HASH_HandleTypeDef structure that contains |
| * the configuration information for HASH module |
| * @retval HAL status |
| */ |
| HAL_StatusTypeDef HAL_HASH_Init(HASH_HandleTypeDef *hhash) |
| { |
| /* Check the hash handle allocation */ |
| if(hhash == NULL) |
| { |
| return HAL_ERROR; |
| } |
| |
| /* Check the parameters */ |
| assert_param(IS_HASH_DATATYPE(hhash->Init.DataType)); |
| |
| if(hhash->State == HAL_HASH_STATE_RESET) |
| { |
| /* Allocate lock resource and initialize it */ |
| hhash->Lock = HAL_UNLOCKED; |
| /* Init the low level hardware */ |
| HAL_HASH_MspInit(hhash); |
| } |
| |
| /* Change the HASH state */ |
| hhash->State = HAL_HASH_STATE_BUSY; |
| |
| /* Reset HashInCount, HashBuffSize and HashITCounter */ |
| hhash->HashInCount = 0; |
| hhash->HashBuffSize = 0; |
| hhash->HashITCounter = 0; |
| |
| /* Set the data type */ |
| HASH->CR |= (uint32_t) (hhash->Init.DataType); |
| |
| /* Change the HASH state */ |
| hhash->State = HAL_HASH_STATE_READY; |
| |
| /* Set the default HASH phase */ |
| hhash->Phase = HAL_HASH_PHASE_READY; |
| |
| /* Return function status */ |
| return HAL_OK; |
| } |
| |
| /** |
| * @brief DeInitializes the HASH peripheral. |
| * @note This API must be called before starting a new processing. |
| * @param hhash pointer to a HASH_HandleTypeDef structure that contains |
| * the configuration information for HASH module |
| * @retval HAL status |
| */ |
| HAL_StatusTypeDef HAL_HASH_DeInit(HASH_HandleTypeDef *hhash) |
| { |
| /* Check the HASH handle allocation */ |
| if(hhash == NULL) |
| { |
| return HAL_ERROR; |
| } |
| |
| /* Change the HASH state */ |
| hhash->State = HAL_HASH_STATE_BUSY; |
| |
| /* Set the default HASH phase */ |
| hhash->Phase = HAL_HASH_PHASE_READY; |
| |
| /* Reset HashInCount, HashBuffSize and HashITCounter */ |
| hhash->HashInCount = 0; |
| hhash->HashBuffSize = 0; |
| hhash->HashITCounter = 0; |
| |
| /* DeInit the low level hardware */ |
| HAL_HASH_MspDeInit(hhash); |
| |
| /* Change the HASH state */ |
| hhash->State = HAL_HASH_STATE_RESET; |
| |
| /* Release Lock */ |
| __HAL_UNLOCK(hhash); |
| |
| /* Return function status */ |
| return HAL_OK; |
| } |
| |
| /** |
| * @brief Initializes the HASH MSP. |
| * @param hhash pointer to a HASH_HandleTypeDef structure that contains |
| * the configuration information for HASH module |
| * @retval None |
| */ |
| __weak void HAL_HASH_MspInit(HASH_HandleTypeDef *hhash) |
| { |
| /* Prevent unused argument(s) compilation warning */ |
| UNUSED(hhash); |
| |
| /* NOTE: This function Should not be modified, when the callback is needed, |
| the HAL_HASH_MspInit could be implemented in the user file |
| */ |
| } |
| |
| /** |
| * @brief DeInitializes HASH MSP. |
| * @param hhash pointer to a HASH_HandleTypeDef structure that contains |
| * the configuration information for HASH module |
| * @retval None |
| */ |
| __weak void HAL_HASH_MspDeInit(HASH_HandleTypeDef *hhash) |
| { |
| /* Prevent unused argument(s) compilation warning */ |
| UNUSED(hhash); |
| |
| /* NOTE: This function Should not be modified, when the callback is needed, |
| the HAL_HASH_MspDeInit could be implemented in the user file |
| */ |
| } |
| |
| /** |
| * @brief Input data transfer complete callback. |
| * @param hhash pointer to a HASH_HandleTypeDef structure that contains |
| * the configuration information for HASH module |
| * @retval None |
| */ |
| __weak void HAL_HASH_InCpltCallback(HASH_HandleTypeDef *hhash) |
| { |
| /* Prevent unused argument(s) compilation warning */ |
| UNUSED(hhash); |
| |
| /* NOTE: This function Should not be modified, when the callback is needed, |
| the HAL_HASH_InCpltCallback could be implemented in the user file |
| */ |
| } |
| |
| /** |
| * @brief Data transfer Error callback. |
| * @param hhash pointer to a HASH_HandleTypeDef structure that contains |
| * the configuration information for HASH module |
| * @retval None |
| */ |
| __weak void HAL_HASH_ErrorCallback(HASH_HandleTypeDef *hhash) |
| { |
| /* Prevent unused argument(s) compilation warning */ |
| UNUSED(hhash); |
| |
| /* NOTE: This function Should not be modified, when the callback is needed, |
| the HAL_HASH_ErrorCallback could be implemented in the user file |
| */ |
| } |
| |
| /** |
| * @brief Digest computation complete callback. It is used only with interrupt. |
| * @note This callback is not relevant with DMA. |
| * @param hhash pointer to a HASH_HandleTypeDef structure that contains |
| * the configuration information for HASH module |
| * @retval None |
| */ |
| __weak void HAL_HASH_DgstCpltCallback(HASH_HandleTypeDef *hhash) |
| { |
| /* Prevent unused argument(s) compilation warning */ |
| UNUSED(hhash); |
| |
| /* NOTE: This function Should not be modified, when the callback is needed, |
| the HAL_HASH_DgstCpltCallback could be implemented in the user file |
| */ |
| } |
| |
| /** |
| * @} |
| */ |
| |
| /** @defgroup HASH_Exported_Functions_Group2 HASH processing functions using polling mode |
| * @brief processing functions using polling mode |
| * |
| @verbatim |
| =============================================================================== |
| ##### HASH processing using polling mode functions##### |
| =============================================================================== |
| [..] This section provides functions allowing to calculate in polling mode |
| the hash value using one of the following algorithms: |
| (+) MD5 |
| (+) SHA1 |
| |
| @endverbatim |
| * @{ |
| */ |
| |
| /** |
| * @brief Initializes the HASH peripheral in MD5 mode then processes pInBuffer. |
| The digest is available in pOutBuffer. |
| * @param hhash pointer to a HASH_HandleTypeDef structure that contains |
| * the configuration information for HASH module |
| * @param pInBuffer Pointer to the input buffer (buffer to be hashed). |
| * @param Size Length of the input buffer in bytes. |
| * If the Size is multiple of 64 bytes, appending the input buffer is possible. |
| * If the Size is not multiple of 64 bytes, the padding is managed by hardware |
| * and appending the input buffer is no more possible. |
| * @param pOutBuffer Pointer to the computed digest. Its size must be 16 bytes. |
| * @param Timeout Timeout value |
| * @retval HAL status |
| */ |
| HAL_StatusTypeDef HAL_HASH_MD5_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout) |
| { |
| uint32_t tickstart = 0; |
| |
| /* Process Locked */ |
| __HAL_LOCK(hhash); |
| |
| /* Change the HASH state */ |
| hhash->State = HAL_HASH_STATE_BUSY; |
| |
| /* Check if initialization phase has already been performed */ |
| if(hhash->Phase == HAL_HASH_PHASE_READY) |
| { |
| /* Select the MD5 mode and reset the HASH processor core, so that the HASH will be ready to compute |
| the message digest of a new message */ |
| HASH->CR |= HASH_ALGOSELECTION_MD5 | HASH_CR_INIT; |
| } |
| |
| /* Set the phase */ |
| hhash->Phase = HAL_HASH_PHASE_PROCESS; |
| |
| /* Configure the number of valid bits in last word of the message */ |
| __HAL_HASH_SET_NBVALIDBITS(Size); |
| |
| /* Write input buffer in data register */ |
| HASH_WriteData(pInBuffer, Size); |
| |
| /* Start the digest calculation */ |
| __HAL_HASH_START_DIGEST(); |
| |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| |
| while(HAL_IS_BIT_SET(HASH->SR, HASH_FLAG_BUSY)) |
| { |
| /* Check for the Timeout */ |
| if(Timeout != HAL_MAX_DELAY) |
| { |
| if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout)) |
| { |
| /* Change state */ |
| hhash->State = HAL_HASH_STATE_TIMEOUT; |
| |
| /* Process Unlocked */ |
| __HAL_UNLOCK(hhash); |
| |
| return HAL_TIMEOUT; |
| } |
| } |
| } |
| |
| /* Read the message digest */ |
| HASH_GetDigest(pOutBuffer, 16); |
| |
| /* Change the HASH state */ |
| hhash->State = HAL_HASH_STATE_READY; |
| |
| /* Process Unlocked */ |
| __HAL_UNLOCK(hhash); |
| |
| /* Return function status */ |
| return HAL_OK; |
| } |
| |
| /** |
| * @brief Initializes the HASH peripheral in MD5 mode then writes the pInBuffer. |
| * @param hhash pointer to a HASH_HandleTypeDef structure that contains |
| * the configuration information for HASH module |
| * @param pInBuffer Pointer to the input buffer (buffer to be hashed). |
| * @param Size Length of the input buffer in bytes. |
| * If the Size is multiple of 64 bytes, appending the input buffer is possible. |
| * If the Size is not multiple of 64 bytes, the padding is managed by hardware |
| * and appending the input buffer is no more possible. |
| * @retval HAL status |
| */ |
| HAL_StatusTypeDef HAL_HASH_MD5_Accumulate(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) |
| { |
| /* Process Locked */ |
| __HAL_LOCK(hhash); |
| |
| /* Change the HASH state */ |
| hhash->State = HAL_HASH_STATE_BUSY; |
| |
| /* Check if initialization phase has already been performed */ |
| if(hhash->Phase == HAL_HASH_PHASE_READY) |
| { |
| /* Select the MD5 mode and reset the HASH processor core, so that the HASH will be ready to compute |
| the message digest of a new message */ |
| HASH->CR |= HASH_ALGOSELECTION_MD5 | HASH_CR_INIT; |
| } |
| |
| /* Set the phase */ |
| hhash->Phase = HAL_HASH_PHASE_PROCESS; |
| |
| /* Configure the number of valid bits in last word of the message */ |
| __HAL_HASH_SET_NBVALIDBITS(Size); |
| |
| /* Write input buffer in data register */ |
| HASH_WriteData(pInBuffer, Size); |
| |
| /* Change the HASH state */ |
| hhash->State = HAL_HASH_STATE_READY; |
| |
| /* Process Unlocked */ |
| __HAL_UNLOCK(hhash); |
| |
| /* Return function status */ |
| return HAL_OK; |
| } |
| |
| /** |
| * @brief Initializes the HASH peripheral in SHA1 mode then processes pInBuffer. |
| The digest is available in pOutBuffer. |
| * @param hhash pointer to a HASH_HandleTypeDef structure that contains |
| * the configuration information for HASH module |
| * @param pInBuffer Pointer to the input buffer (buffer to be hashed). |
| * @param Size Length of the input buffer in bytes. |
| * If the Size is not multiple of 64 bytes, the padding is managed by hardware. |
| * @param pOutBuffer Pointer to the computed digest. Its size must be 20 bytes. |
| * @param Timeout Timeout value |
| * @retval HAL status |
| */ |
| HAL_StatusTypeDef HAL_HASH_SHA1_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout) |
| { |
| uint32_t tickstart = 0; |
| |
| /* Process Locked */ |
| __HAL_LOCK(hhash); |
| |
| /* Change the HASH state */ |
| hhash->State = HAL_HASH_STATE_BUSY; |
| |
| /* Check if initialization phase has already been performed */ |
| if(hhash->Phase == HAL_HASH_PHASE_READY) |
| { |
| /* Select the SHA1 mode and reset the HASH processor core, so that the HASH will be ready to compute |
| the message digest of a new message */ |
| HASH->CR |= HASH_ALGOSELECTION_SHA1 | HASH_CR_INIT; |
| } |
| |
| /* Set the phase */ |
| hhash->Phase = HAL_HASH_PHASE_PROCESS; |
| |
| /* Configure the number of valid bits in last word of the message */ |
| __HAL_HASH_SET_NBVALIDBITS(Size); |
| |
| /* Write input buffer in data register */ |
| HASH_WriteData(pInBuffer, Size); |
| |
| /* Start the digest calculation */ |
| __HAL_HASH_START_DIGEST(); |
| |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| |
| while(HAL_IS_BIT_SET(HASH->SR, HASH_FLAG_BUSY)) |
| { |
| /* Check for the Timeout */ |
| if(Timeout != HAL_MAX_DELAY) |
| { |
| if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout)) |
| { |
| /* Change state */ |
| hhash->State = HAL_HASH_STATE_TIMEOUT; |
| |
| /* Process Unlocked */ |
| __HAL_UNLOCK(hhash); |
| |
| return HAL_TIMEOUT; |
| } |
| } |
| } |
| |
| /* Read the message digest */ |
| HASH_GetDigest(pOutBuffer, 20); |
| |
| /* Change the HASH state */ |
| hhash->State = HAL_HASH_STATE_READY; |
| |
| /* Process Unlocked */ |
| __HAL_UNLOCK(hhash); |
| |
| /* Return function status */ |
| return HAL_OK; |
| } |
| |
| /** |
| * @brief Initializes the HASH peripheral in SHA1 mode then processes pInBuffer. |
| * @param hhash pointer to a HASH_HandleTypeDef structure that contains |
| * the configuration information for HASH module |
| * @param pInBuffer Pointer to the input buffer (buffer to be hashed). |
| * @param Size Length of the input buffer in bytes. |
| * If the Size is not multiple of 64 bytes, the padding is managed by hardware. |
| * @note Input buffer size in bytes must be a multiple of 4 otherwise the digest computation is corrupted. |
| * @retval HAL status |
| */ |
| HAL_StatusTypeDef HAL_HASH_SHA1_Accumulate(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) |
| { |
| /* Check the parameters */ |
| assert_param(IS_HASH_SHA1_BUFFER_SIZE(Size)); |
| |
| /* Process Locked */ |
| __HAL_LOCK(hhash); |
| |
| /* Change the HASH state */ |
| hhash->State = HAL_HASH_STATE_BUSY; |
| |
| /* Check if initialization phase has already been performed */ |
| if(hhash->Phase == HAL_HASH_PHASE_READY) |
| { |
| /* Select the SHA1 mode and reset the HASH processor core, so that the HASH will be ready to compute |
| the message digest of a new message */ |
| HASH->CR |= HASH_ALGOSELECTION_SHA1 | HASH_CR_INIT; |
| } |
| |
| /* Set the phase */ |
| hhash->Phase = HAL_HASH_PHASE_PROCESS; |
| |
| /* Configure the number of valid bits in last word of the message */ |
| __HAL_HASH_SET_NBVALIDBITS(Size); |
| |
| /* Write input buffer in data register */ |
| HASH_WriteData(pInBuffer, Size); |
| |
| /* Change the HASH state */ |
| hhash->State = HAL_HASH_STATE_READY; |
| |
| /* Process Unlocked */ |
| __HAL_UNLOCK(hhash); |
| |
| /* Return function status */ |
| return HAL_OK; |
| } |
| |
| /** |
| * @} |
| */ |
| |
| /** @defgroup HASH_Exported_Functions_Group3 HASH processing functions using interrupt mode |
| * @brief processing functions using interrupt mode. |
| * |
| @verbatim |
| =============================================================================== |
| ##### HASH processing using interrupt mode functions ##### |
| =============================================================================== |
| [..] This section provides functions allowing to calculate in interrupt mode |
| the hash value using one of the following algorithms: |
| (+) MD5 |
| (+) SHA1 |
| |
| @endverbatim |
| * @{ |
| */ |
| |
| /** |
| * @brief Initializes the HASH peripheral in MD5 mode then processes pInBuffer. |
| * The digest is available in pOutBuffer. |
| * @param hhash pointer to a HASH_HandleTypeDef structure that contains |
| * the configuration information for HASH module |
| * @param pInBuffer Pointer to the input buffer (buffer to be hashed). |
| * @param Size Length of the input buffer in bytes. |
| * If the Size is not multiple of 64 bytes, the padding is managed by hardware. |
| * @param pOutBuffer Pointer to the computed digest. Its size must be 16 bytes. |
| * @retval HAL status |
| */ |
| HAL_StatusTypeDef HAL_HASH_MD5_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer) |
| { |
| uint32_t inputaddr; |
| uint32_t outputaddr; |
| uint32_t buffercounter; |
| uint32_t inputcounter; |
| |
| /* Process Locked */ |
| __HAL_LOCK(hhash); |
| |
| if(hhash->State == HAL_HASH_STATE_READY) |
| { |
| /* Change the HASH state */ |
| hhash->State = HAL_HASH_STATE_BUSY; |
| |
| hhash->HashInCount = Size; |
| hhash->pHashInBuffPtr = pInBuffer; |
| hhash->pHashOutBuffPtr = pOutBuffer; |
| |
| /* Check if initialization phase has already been performed */ |
| if(hhash->Phase == HAL_HASH_PHASE_READY) |
| { |
| /* Select the SHA1 mode */ |
| HASH->CR |= HASH_ALGOSELECTION_MD5; |
| /* Reset the HASH processor core, so that the HASH will be ready to compute |
| the message digest of a new message */ |
| HASH->CR |= HASH_CR_INIT; |
| } |
| |
| /* Reset interrupt counter */ |
| hhash->HashITCounter = 0; |
| |
| /* Set the phase */ |
| hhash->Phase = HAL_HASH_PHASE_PROCESS; |
| |
| /* Process Unlocked */ |
| __HAL_UNLOCK(hhash); |
| |
| /* Enable Interrupts */ |
| HASH->IMR = (HASH_IT_DINI | HASH_IT_DCI); |
| |
| /* Return function status */ |
| return HAL_OK; |
| } |
| if(__HAL_HASH_GET_FLAG(HASH_FLAG_DCIS)) |
| { |
| outputaddr = (uint32_t)hhash->pHashOutBuffPtr; |
| /* Read the Output block from the Output FIFO */ |
| *(uint32_t*)(outputaddr) = __REV(HASH->HR[0]); |
| outputaddr+=4; |
| *(uint32_t*)(outputaddr) = __REV(HASH->HR[1]); |
| outputaddr+=4; |
| *(uint32_t*)(outputaddr) = __REV(HASH->HR[2]); |
| outputaddr+=4; |
| *(uint32_t*)(outputaddr) = __REV(HASH->HR[3]); |
| |
| if(hhash->HashInCount == 0) |
| { |
| /* Disable Interrupts */ |
| HASH->IMR = 0; |
| /* Change the HASH state */ |
| hhash->State = HAL_HASH_STATE_READY; |
| /* Call digest computation complete callback */ |
| HAL_HASH_DgstCpltCallback(hhash); |
| |
| /* Process Unlocked */ |
| __HAL_UNLOCK(hhash); |
| |
| /* Return function status */ |
| return HAL_OK; |
| } |
| } |
| |
| if(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS)) |
| { |
| if(hhash->HashInCount >= 68) |
| { |
| inputaddr = (uint32_t)hhash->pHashInBuffPtr; |
| /* Write the Input block in the Data IN register */ |
| for(buffercounter = 0; buffercounter < 64; buffercounter+=4) |
| { |
| HASH->DIN = *(uint32_t*)inputaddr; |
| inputaddr+=4; |
| } |
| if(hhash->HashITCounter == 0) |
| { |
| HASH->DIN = *(uint32_t*)inputaddr; |
| |
| if(hhash->HashInCount >= 68) |
| { |
| /* Decrement buffer counter */ |
| hhash->HashInCount -= 68; |
| hhash->pHashInBuffPtr+= 68; |
| } |
| else |
| { |
| hhash->HashInCount = 0; |
| hhash->pHashInBuffPtr+= hhash->HashInCount; |
| } |
| /* Set Interrupt counter */ |
| hhash->HashITCounter = 1; |
| } |
| else |
| { |
| /* Decrement buffer counter */ |
| hhash->HashInCount -= 64; |
| hhash->pHashInBuffPtr+= 64; |
| } |
| } |
| else |
| { |
| /* Get the buffer address */ |
| inputaddr = (uint32_t)hhash->pHashInBuffPtr; |
| /* Get the buffer counter */ |
| inputcounter = hhash->HashInCount; |
| /* Disable Interrupts */ |
| HASH->IMR &= ~(HASH_IT_DINI); |
| /* Configure the number of valid bits in last word of the message */ |
| __HAL_HASH_SET_NBVALIDBITS(inputcounter); |
| |
| if((inputcounter > 4) && (inputcounter%4)) |
| { |
| inputcounter = (inputcounter+4-inputcounter%4); |
| } |
| else if ((inputcounter < 4) && (inputcounter != 0)) |
| { |
| inputcounter = 4; |
| } |
| |
| /* Write the Input block in the Data IN register */ |
| for(buffercounter = 0; buffercounter < inputcounter/4; buffercounter++) |
| { |
| HASH->DIN = *(uint32_t*)inputaddr; |
| inputaddr+=4; |
| } |
| /* Start the digest calculation */ |
| __HAL_HASH_START_DIGEST(); |
| /* Reset buffer counter */ |
| hhash->HashInCount = 0; |
| /* Call Input data transfer complete callback */ |
| HAL_HASH_InCpltCallback(hhash); |
| } |
| } |
| |
| /* Process Unlocked */ |
| __HAL_UNLOCK(hhash); |
| |
| /* Return function status */ |
| return HAL_OK; |
| } |
| |
| /** |
| * @brief Initializes the HASH peripheral in SHA1 mode then processes pInBuffer. |
| * The digest is available in pOutBuffer. |
| * @param hhash pointer to a HASH_HandleTypeDef structure that contains |
| * the configuration information for HASH module |
| * @param pInBuffer Pointer to the input buffer (buffer to be hashed). |
| * @param Size Length of the input buffer in bytes. |
| * If the Size is not multiple of 64 bytes, the padding is managed by hardware. |
| * @param pOutBuffer Pointer to the computed digest. Its size must be 20 bytes. |
| * @retval HAL status |
| */ |
| HAL_StatusTypeDef HAL_HASH_SHA1_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer) |
| { |
| uint32_t inputaddr; |
| uint32_t outputaddr; |
| uint32_t buffercounter; |
| uint32_t inputcounter; |
| |
| /* Process Locked */ |
| __HAL_LOCK(hhash); |
| |
| if(hhash->State == HAL_HASH_STATE_READY) |
| { |
| /* Change the HASH state */ |
| hhash->State = HAL_HASH_STATE_BUSY; |
| |
| hhash->HashInCount = Size; |
| hhash->pHashInBuffPtr = pInBuffer; |
| hhash->pHashOutBuffPtr = pOutBuffer; |
| |
| /* Check if initialization phase has already been performed */ |
| if(hhash->Phase == HAL_HASH_PHASE_READY) |
| { |
| /* Select the SHA1 mode */ |
| HASH->CR |= HASH_ALGOSELECTION_SHA1; |
| /* Reset the HASH processor core, so that the HASH will be ready to compute |
| the message digest of a new message */ |
| HASH->CR |= HASH_CR_INIT; |
| } |
| |
| /* Reset interrupt counter */ |
| hhash->HashITCounter = 0; |
| |
| /* Set the phase */ |
| hhash->Phase = HAL_HASH_PHASE_PROCESS; |
| |
| /* Process Unlocked */ |
| __HAL_UNLOCK(hhash); |
| |
| /* Enable Interrupts */ |
| HASH->IMR = (HASH_IT_DINI | HASH_IT_DCI); |
| |
| /* Return function status */ |
| return HAL_OK; |
| } |
| if(__HAL_HASH_GET_FLAG(HASH_FLAG_DCIS)) |
| { |
| outputaddr = (uint32_t)hhash->pHashOutBuffPtr; |
| /* Read the Output block from the Output FIFO */ |
| *(uint32_t*)(outputaddr) = __REV(HASH->HR[0]); |
| outputaddr+=4; |
| *(uint32_t*)(outputaddr) = __REV(HASH->HR[1]); |
| outputaddr+=4; |
| *(uint32_t*)(outputaddr) = __REV(HASH->HR[2]); |
| outputaddr+=4; |
| *(uint32_t*)(outputaddr) = __REV(HASH->HR[3]); |
| outputaddr+=4; |
| *(uint32_t*)(outputaddr) = __REV(HASH->HR[4]); |
| if(hhash->HashInCount == 0) |
| { |
| /* Disable Interrupts */ |
| HASH->IMR = 0; |
| /* Change the HASH state */ |
| hhash->State = HAL_HASH_STATE_READY; |
| /* Call digest computation complete callback */ |
| HAL_HASH_DgstCpltCallback(hhash); |
| |
| /* Process Unlocked */ |
| __HAL_UNLOCK(hhash); |
| |
| /* Return function status */ |
| return HAL_OK; |
| } |
| } |
| if(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS)) |
| { |
| if(hhash->HashInCount >= 68) |
| { |
| inputaddr = (uint32_t)hhash->pHashInBuffPtr; |
| /* Write the Input block in the Data IN register */ |
| for(buffercounter = 0; buffercounter < 64; buffercounter+=4) |
| { |
| HASH->DIN = *(uint32_t*)inputaddr; |
| inputaddr+=4; |
| } |
| if(hhash->HashITCounter == 0) |
| { |
| HASH->DIN = *(uint32_t*)inputaddr; |
| |
| if(hhash->HashInCount >= 68) |
| { |
| /* Decrement buffer counter */ |
| hhash->HashInCount -= 68; |
| hhash->pHashInBuffPtr+= 68; |
| } |
| else |
| { |
| hhash->HashInCount = 0; |
| hhash->pHashInBuffPtr+= hhash->HashInCount; |
| } |
| /* Set Interrupt counter */ |
| hhash->HashITCounter = 1; |
| } |
| else |
| { |
| /* Decrement buffer counter */ |
| hhash->HashInCount -= 64; |
| hhash->pHashInBuffPtr+= 64; |
| } |
| } |
| else |
| { |
| /* Get the buffer address */ |
| inputaddr = (uint32_t)hhash->pHashInBuffPtr; |
| /* Get the buffer counter */ |
| inputcounter = hhash->HashInCount; |
| /* Disable Interrupts */ |
| HASH->IMR &= ~(HASH_IT_DINI); |
| /* Configure the number of valid bits in last word of the message */ |
| __HAL_HASH_SET_NBVALIDBITS(inputcounter); |
| |
| if((inputcounter > 4) && (inputcounter%4)) |
| { |
| inputcounter = (inputcounter+4-inputcounter%4); |
| } |
| else if ((inputcounter < 4) && (inputcounter != 0)) |
| { |
| inputcounter = 4; |
| } |
| /* Write the Input block in the Data IN register */ |
| for(buffercounter = 0; buffercounter < inputcounter/4; buffercounter++) |
| { |
| HASH->DIN = *(uint32_t*)inputaddr; |
| inputaddr+=4; |
| } |
| /* Start the digest calculation */ |
| __HAL_HASH_START_DIGEST(); |
| /* Reset buffer counter */ |
| hhash->HashInCount = 0; |
| /* Call Input data transfer complete callback */ |
| HAL_HASH_InCpltCallback(hhash); |
| } |
| } |
| |
| /* Process Unlocked */ |
| __HAL_UNLOCK(hhash); |
| |
| /* Return function status */ |
| return HAL_OK; |
| } |
| |
| /** |
| * @brief This function handles HASH interrupt request. |
| * @param hhash pointer to a HASH_HandleTypeDef structure that contains |
| * the configuration information for HASH module |
| * @retval None |
| */ |
| void HAL_HASH_IRQHandler(HASH_HandleTypeDef *hhash) |
| { |
| switch(HASH->CR & HASH_CR_ALGO) |
| { |
| case HASH_ALGOSELECTION_MD5: |
| HAL_HASH_MD5_Start_IT(hhash, NULL, 0, NULL); |
| break; |
| |
| case HASH_ALGOSELECTION_SHA1: |
| HAL_HASH_SHA1_Start_IT(hhash, NULL, 0, NULL); |
| break; |
| |
| default: |
| break; |
| } |
| } |
| |
| /** |
| * @} |
| */ |
| |
| /** @defgroup HASH_Exported_Functions_Group4 HASH processing functions using DMA mode |
| * @brief processing functions using DMA mode. |
| * |
| @verbatim |
| =============================================================================== |
| ##### HASH processing using DMA mode functions ##### |
| =============================================================================== |
| [..] This section provides functions allowing to calculate in DMA mode |
| the hash value using one of the following algorithms: |
| (+) MD5 |
| (+) SHA1 |
| |
| @endverbatim |
| * @{ |
| */ |
| |
| /** |
| * @brief Initializes the HASH peripheral in MD5 mode then enables DMA to |
| control data transfer. Use HAL_HASH_MD5_Finish() to get the digest. |
| * @param hhash pointer to a HASH_HandleTypeDef structure that contains |
| * the configuration information for HASH module |
| * @param pInBuffer Pointer to the input buffer (buffer to be hashed). |
| * @param Size Length of the input buffer in bytes. |
| * If the Size is not multiple of 64 bytes, the padding is managed by hardware. |
| * @retval HAL status |
| */ |
| HAL_StatusTypeDef HAL_HASH_MD5_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) |
| { |
| uint32_t inputaddr = (uint32_t)pInBuffer; |
| |
| /* Process Locked */ |
| __HAL_LOCK(hhash); |
| |
| /* Change the HASH state */ |
| hhash->State = HAL_HASH_STATE_BUSY; |
| |
| /* Check if initialization phase has already been performed */ |
| if(hhash->Phase == HAL_HASH_PHASE_READY) |
| { |
| /* Select the MD5 mode and reset the HASH processor core, so that the HASH will be ready to compute |
| the message digest of a new message */ |
| HASH->CR |= HASH_ALGOSELECTION_MD5 | HASH_CR_INIT; |
| } |
| |
| /* Configure the number of valid bits in last word of the message */ |
| __HAL_HASH_SET_NBVALIDBITS(Size); |
| |
| /* Set the phase */ |
| hhash->Phase = HAL_HASH_PHASE_PROCESS; |
| |
| /* Set the HASH DMA transfer complete callback */ |
| hhash->hdmain->XferCpltCallback = HASH_DMAXferCplt; |
| /* Set the DMA error callback */ |
| hhash->hdmain->XferErrorCallback = HASH_DMAError; |
| |
| /* Enable the DMA In DMA Stream */ |
| HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, (Size%4 ? (Size+3)/4:Size/4)); |
| |
| /* Enable DMA requests */ |
| HASH->CR |= (HASH_CR_DMAE); |
| |
| /* Process Unlocked */ |
| __HAL_UNLOCK(hhash); |
| |
| /* Return function status */ |
| return HAL_OK; |
| } |
| |
| /** |
| * @brief Returns the computed digest in MD5 mode |
| * @param hhash pointer to a HASH_HandleTypeDef structure that contains |
| * the configuration information for HASH module |
| * @param pOutBuffer Pointer to the computed digest. Its size must be 16 bytes. |
| * @param Timeout Timeout value |
| * @retval HAL status |
| */ |
| HAL_StatusTypeDef HAL_HASH_MD5_Finish(HASH_HandleTypeDef *hhash, uint8_t* pOutBuffer, uint32_t Timeout) |
| { |
| uint32_t tickstart = 0; |
| |
| /* Process Locked */ |
| __HAL_LOCK(hhash); |
| |
| /* Change HASH peripheral state */ |
| hhash->State = HAL_HASH_STATE_BUSY; |
| |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| |
| while(HAL_IS_BIT_CLR(HASH->SR, HASH_FLAG_DCIS)) |
| { |
| /* Check for the Timeout */ |
| if(Timeout != HAL_MAX_DELAY) |
| { |
| if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout)) |
| { |
| /* Change state */ |
| hhash->State = HAL_HASH_STATE_TIMEOUT; |
| |
| /* Process Unlocked */ |
| __HAL_UNLOCK(hhash); |
| |
| return HAL_TIMEOUT; |
| } |
| } |
| } |
| |
| /* Read the message digest */ |
| HASH_GetDigest(pOutBuffer, 16); |
| |
| /* Change HASH peripheral state */ |
| hhash->State = HAL_HASH_STATE_READY; |
| |
| /* Process Unlocked */ |
| __HAL_UNLOCK(hhash); |
| |
| /* Return function status */ |
| return HAL_OK; |
| } |
| |
| /** |
| * @brief Initializes the HASH peripheral in SHA1 mode then enables DMA to |
| control data transfer. Use HAL_HASH_SHA1_Finish() to get the digest. |
| * @param hhash pointer to a HASH_HandleTypeDef structure that contains |
| * the configuration information for HASH module |
| * @param pInBuffer Pointer to the input buffer (buffer to be hashed). |
| * @param Size Length of the input buffer in bytes. |
| * If the Size is not multiple of 64 bytes, the padding is managed by hardware. |
| * @retval HAL status |
| */ |
| HAL_StatusTypeDef HAL_HASH_SHA1_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) |
| { |
| uint32_t inputaddr = (uint32_t)pInBuffer; |
| |
| /* Process Locked */ |
| __HAL_LOCK(hhash); |
| |
| /* Change the HASH state */ |
| hhash->State = HAL_HASH_STATE_BUSY; |
| |
| /* Check if initialization phase has already been performed */ |
| if(hhash->Phase == HAL_HASH_PHASE_READY) |
| { |
| /* Select the SHA1 mode and reset the HASH processor core, so that the HASH will be ready to compute |
| the message digest of a new message */ |
| HASH->CR |= HASH_ALGOSELECTION_SHA1; |
| HASH->CR |= HASH_CR_INIT; |
| } |
| |
| /* Configure the number of valid bits in last word of the message */ |
| __HAL_HASH_SET_NBVALIDBITS(Size); |
| |
| /* Set the phase */ |
| hhash->Phase = HAL_HASH_PHASE_PROCESS; |
| |
| /* Set the HASH DMA transfer complete callback */ |
| hhash->hdmain->XferCpltCallback = HASH_DMAXferCplt; |
| /* Set the DMA error callback */ |
| hhash->hdmain->XferErrorCallback = HASH_DMAError; |
| |
| /* Enable the DMA In DMA Stream */ |
| HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, (Size%4 ? (Size+3)/4:Size/4)); |
| |
| /* Enable DMA requests */ |
| HASH->CR |= (HASH_CR_DMAE); |
| |
| /* Process Unlocked */ |
| __HAL_UNLOCK(hhash); |
| |
| /* Return function status */ |
| return HAL_OK; |
| } |
| |
| /** |
| * @brief Returns the computed digest in SHA1 mode. |
| * @param hhash pointer to a HASH_HandleTypeDef structure that contains |
| * the configuration information for HASH module |
| * @param pOutBuffer Pointer to the computed digest. Its size must be 20 bytes. |
| * @param Timeout Timeout value |
| * @retval HAL status |
| */ |
| HAL_StatusTypeDef HAL_HASH_SHA1_Finish(HASH_HandleTypeDef *hhash, uint8_t* pOutBuffer, uint32_t Timeout) |
| { |
| uint32_t tickstart = 0; |
| |
| /* Process Locked */ |
| __HAL_LOCK(hhash); |
| |
| /* Change HASH peripheral state */ |
| hhash->State = HAL_HASH_STATE_BUSY; |
| |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| while(HAL_IS_BIT_CLR(HASH->SR, HASH_FLAG_DCIS)) |
| { |
| /* Check for the Timeout */ |
| if(Timeout != HAL_MAX_DELAY) |
| { |
| if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout)) |
| { |
| /* Change state */ |
| hhash->State = HAL_HASH_STATE_TIMEOUT; |
| |
| /* Process Unlocked */ |
| __HAL_UNLOCK(hhash); |
| |
| return HAL_TIMEOUT; |
| } |
| } |
| } |
| |
| /* Read the message digest */ |
| HASH_GetDigest(pOutBuffer, 20); |
| |
| /* Change HASH peripheral state */ |
| hhash->State = HAL_HASH_STATE_READY; |
| |
| /* Process UnLock */ |
| __HAL_UNLOCK(hhash); |
| |
| /* Return function status */ |
| return HAL_OK; |
| } |
| |
| |
| /** |
| * @} |
| */ |
| |
| /** @defgroup HASH_Exported_Functions_Group5 HASH-MAC (HMAC) processing functions using polling mode |
| * @brief HMAC processing functions using polling mode . |
| * |
| @verbatim |
| =============================================================================== |
| ##### HMAC processing using polling mode functions ##### |
| =============================================================================== |
| [..] This section provides functions allowing to calculate in polling mode |
| the HMAC value using one of the following algorithms: |
| (+) MD5 |
| (+) SHA1 |
| |
| @endverbatim |
| * @{ |
| */ |
| |
| /** |
| * @brief Initializes the HASH peripheral in HMAC MD5 mode |
| * then processes pInBuffer. The digest is available in pOutBuffer |
| * @param hhash pointer to a HASH_HandleTypeDef structure that contains |
| * the configuration information for HASH module |
| * @param pInBuffer Pointer to the input buffer (buffer to be hashed). |
| * @param Size Length of the input buffer in bytes. |
| * If the Size is not multiple of 64 bytes, the padding is managed by hardware. |
| * @param pOutBuffer Pointer to the computed digest. Its size must be 20 bytes. |
| * @param Timeout Timeout value |
| * @retval HAL status |
| */ |
| HAL_StatusTypeDef HAL_HMAC_MD5_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout) |
| { |
| uint32_t tickstart = 0; |
| |
| /* Process Locked */ |
| __HAL_LOCK(hhash); |
| |
| /* Change the HASH state */ |
| hhash->State = HAL_HASH_STATE_BUSY; |
| |
| /* Check if initialization phase has already been performed */ |
| if(hhash->Phase == HAL_HASH_PHASE_READY) |
| { |
| /* Check if key size is greater than 64 bytes */ |
| if(hhash->Init.KeySize > 64) |
| { |
| /* Select the HMAC MD5 mode */ |
| HASH->CR |= (HASH_ALGOSELECTION_MD5 | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT); |
| } |
| else |
| { |
| /* Select the HMAC MD5 mode */ |
| HASH->CR |= (HASH_ALGOSELECTION_MD5 | HASH_ALGOMODE_HMAC | HASH_CR_INIT); |
| } |
| } |
| |
| /* Set the phase */ |
| hhash->Phase = HAL_HASH_PHASE_PROCESS; |
| |
| /************************** STEP 1 ******************************************/ |
| /* Configure the number of valid bits in last word of the message */ |
| __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize); |
| |
| /* Write input buffer in data register */ |
| HASH_WriteData(hhash->Init.pKey, hhash->Init.KeySize); |
| |
| /* Start the digest calculation */ |
| __HAL_HASH_START_DIGEST(); |
| |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| |
| while(HAL_IS_BIT_SET(HASH->SR, HASH_FLAG_BUSY)) |
| { |
| /* Check for the Timeout */ |
| if(Timeout != HAL_MAX_DELAY) |
| { |
| if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout)) |
| { |
| /* Change state */ |
| hhash->State = HAL_HASH_STATE_TIMEOUT; |
| |
| /* Process Unlocked */ |
| __HAL_UNLOCK(hhash); |
| |
| return HAL_TIMEOUT; |
| } |
| } |
| } |
| /************************** STEP 2 ******************************************/ |
| /* Configure the number of valid bits in last word of the message */ |
| __HAL_HASH_SET_NBVALIDBITS(Size); |
| |
| /* Write input buffer in data register */ |
| HASH_WriteData(pInBuffer, Size); |
| |
| /* Start the digest calculation */ |
| __HAL_HASH_START_DIGEST(); |
| |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| |
| while(HAL_IS_BIT_SET(HASH->SR, HASH_FLAG_BUSY)) |
| { |
| /* Check for the Timeout */ |
| if(Timeout != HAL_MAX_DELAY) |
| { |
| if((HAL_GetTick() - tickstart ) > Timeout) |
| { |
| /* Change state */ |
| hhash->State = HAL_HASH_STATE_TIMEOUT; |
| |
| /* Process Unlocked */ |
| __HAL_UNLOCK(hhash); |
| |
| return HAL_TIMEOUT; |
| } |
| } |
| } |
| /************************** STEP 3 ******************************************/ |
| /* Configure the number of valid bits in last word of the message */ |
| __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize); |
| |
| /* Write input buffer in data register */ |
| HASH_WriteData(hhash->Init.pKey, hhash->Init.KeySize); |
| |
| /* Start the digest calculation */ |
| __HAL_HASH_START_DIGEST(); |
| |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| |
| while(HAL_IS_BIT_SET(HASH->SR, HASH_FLAG_BUSY)) |
| { |
| /* Check for the Timeout */ |
| if(Timeout != HAL_MAX_DELAY) |
| { |
| if((HAL_GetTick() - tickstart ) > Timeout) |
| { |
| /* Change state */ |
| hhash->State = HAL_HASH_STATE_TIMEOUT; |
| |
| /* Process Unlocked */ |
| __HAL_UNLOCK(hhash); |
| |
| return HAL_TIMEOUT; |
| } |
| } |
| } |
| |
| /* Read the message digest */ |
| HASH_GetDigest(pOutBuffer, 16); |
| |
| /* Change the HASH state */ |
| hhash->State = HAL_HASH_STATE_READY; |
| |
| /* Process Unlocked */ |
| __HAL_UNLOCK(hhash); |
| |
| /* Return function status */ |
| return HAL_OK; |
| } |
| |
| /** |
| * @brief Initializes the HASH peripheral in HMAC SHA1 mode |
| * then processes pInBuffer. The digest is available in pOutBuffer. |
| * @param hhash pointer to a HASH_HandleTypeDef structure that contains |
| * the configuration information for HASH module |
| * @param pInBuffer Pointer to the input buffer (buffer to be hashed). |
| * @param Size Length of the input buffer in bytes. |
| * If the Size is not multiple of 64 bytes, the padding is managed by hardware. |
| * @param pOutBuffer Pointer to the computed digest. Its size must be 20 bytes. |
| * @param Timeout Timeout value |
| * @retval HAL status |
| */ |
| HAL_StatusTypeDef HAL_HMAC_SHA1_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout) |
| { |
| uint32_t tickstart = 0; |
| |
| /* Process Locked */ |
| __HAL_LOCK(hhash); |
| |
| /* Change the HASH state */ |
| hhash->State = HAL_HASH_STATE_BUSY; |
| |
| /* Check if initialization phase has already been performed */ |
| if(hhash->Phase == HAL_HASH_PHASE_READY) |
| { |
| /* Check if key size is greater than 64 bytes */ |
| if(hhash->Init.KeySize > 64) |
| { |
| /* Select the HMAC SHA1 mode */ |
| HASH->CR |= (HASH_ALGOSELECTION_SHA1 | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT); |
| } |
| else |
| { |
| /* Select the HMAC SHA1 mode */ |
| HASH->CR |= (HASH_ALGOSELECTION_SHA1 | HASH_ALGOMODE_HMAC | HASH_CR_INIT); |
| } |
| } |
| |
| /* Set the phase */ |
| hhash->Phase = HAL_HASH_PHASE_PROCESS; |
| |
| /************************** STEP 1 ******************************************/ |
| /* Configure the number of valid bits in last word of the message */ |
| __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize); |
| |
| /* Write input buffer in data register */ |
| HASH_WriteData(hhash->Init.pKey, hhash->Init.KeySize); |
| |
| /* Start the digest calculation */ |
| __HAL_HASH_START_DIGEST(); |
| |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| |
| while(HAL_IS_BIT_SET(HASH->SR, HASH_FLAG_BUSY)) |
| { |
| /* Check for the Timeout */ |
| if(Timeout != HAL_MAX_DELAY) |
| { |
| if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout)) |
| { |
| /* Change state */ |
| hhash->State = HAL_HASH_STATE_TIMEOUT; |
| |
| /* Process Unlocked */ |
| __HAL_UNLOCK(hhash); |
| |
| return HAL_TIMEOUT; |
| } |
| } |
| } |
| /************************** STEP 2 ******************************************/ |
| /* Configure the number of valid bits in last word of the message */ |
| __HAL_HASH_SET_NBVALIDBITS(Size); |
| |
| /* Write input buffer in data register */ |
| HASH_WriteData(pInBuffer, Size); |
| |
| /* Start the digest calculation */ |
| __HAL_HASH_START_DIGEST(); |
| |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| |
| while(HAL_IS_BIT_SET(HASH->SR, HASH_FLAG_BUSY)) |
| { |
| /* Check for the Timeout */ |
| if(Timeout != HAL_MAX_DELAY) |
| { |
| if((HAL_GetTick() - tickstart ) > Timeout) |
| { |
| /* Change state */ |
| hhash->State = HAL_HASH_STATE_TIMEOUT; |
| |
| /* Process Unlocked */ |
| __HAL_UNLOCK(hhash); |
| |
| return HAL_TIMEOUT; |
| } |
| } |
| } |
| /************************** STEP 3 ******************************************/ |
| /* Configure the number of valid bits in last word of the message */ |
| __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize); |
| |
| /* Write input buffer in data register */ |
| HASH_WriteData(hhash->Init.pKey, hhash->Init.KeySize); |
| |
| /* Start the digest calculation */ |
| __HAL_HASH_START_DIGEST(); |
| |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| |
| while(HAL_IS_BIT_SET(HASH->SR, HASH_FLAG_BUSY)) |
| { |
| /* Check for the Timeout */ |
| if(Timeout != HAL_MAX_DELAY) |
| { |
| if((HAL_GetTick() - tickstart ) > Timeout) |
| { |
| /* Change state */ |
| hhash->State = HAL_HASH_STATE_TIMEOUT; |
| |
| /* Process Unlocked */ |
| __HAL_UNLOCK(hhash); |
| |
| return HAL_TIMEOUT; |
| } |
| } |
| } |
| /* Read the message digest */ |
| HASH_GetDigest(pOutBuffer, 20); |
| |
| /* Change the HASH state */ |
| hhash->State = HAL_HASH_STATE_READY; |
| |
| /* Process Unlocked */ |
| __HAL_UNLOCK(hhash); |
| |
| /* Return function status */ |
| return HAL_OK; |
| } |
| |
| /** |
| * @} |
| */ |
| |
| /** @defgroup HASH_Exported_Functions_Group6 HASH-MAC (HMAC) processing functions using DMA mode |
| * @brief HMAC processing functions using DMA mode . |
| * |
| @verbatim |
| =============================================================================== |
| ##### HMAC processing using DMA mode functions ##### |
| =============================================================================== |
| [..] This section provides functions allowing to calculate in DMA mode |
| the HMAC value using one of the following algorithms: |
| (+) MD5 |
| (+) SHA1 |
| |
| @endverbatim |
| * @{ |
| */ |
| |
| /** |
| * @brief Initializes the HASH peripheral in HMAC MD5 mode |
| * then enables DMA to control data transfer. |
| * @param hhash pointer to a HASH_HandleTypeDef structure that contains |
| * the configuration information for HASH module |
| * @param pInBuffer Pointer to the input buffer (buffer to be hashed). |
| * @param Size Length of the input buffer in bytes. |
| * If the Size is not multiple of 64 bytes, the padding is managed by hardware. |
| * @retval HAL status |
| */ |
| HAL_StatusTypeDef HAL_HMAC_MD5_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) |
| { |
| uint32_t inputaddr = 0; |
| |
| /* Process Locked */ |
| __HAL_LOCK(hhash); |
| |
| /* Change the HASH state */ |
| hhash->State = HAL_HASH_STATE_BUSY; |
| |
| /* Save buffer pointer and size in handle */ |
| hhash->pHashInBuffPtr = pInBuffer; |
| hhash->HashBuffSize = Size; |
| hhash->HashInCount = 0; |
| |
| /* Check if initialization phase has already been performed */ |
| if(hhash->Phase == HAL_HASH_PHASE_READY) |
| { |
| /* Check if key size is greater than 64 bytes */ |
| if(hhash->Init.KeySize > 64) |
| { |
| /* Select the HMAC MD5 mode */ |
| HASH->CR |= (HASH_ALGOSELECTION_MD5 | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT); |
| } |
| else |
| { |
| /* Select the HMAC MD5 mode */ |
| HASH->CR |= (HASH_ALGOSELECTION_MD5 | HASH_ALGOMODE_HMAC | HASH_CR_INIT); |
| } |
| } |
| |
| /* Set the phase */ |
| hhash->Phase = HAL_HASH_PHASE_PROCESS; |
| |
| /* Configure the number of valid bits in last word of the message */ |
| __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize); |
| |
| /* Get the key address */ |
| inputaddr = (uint32_t)(hhash->Init.pKey); |
| |
| /* Set the HASH DMA transfer complete callback */ |
| hhash->hdmain->XferCpltCallback = HASH_DMAXferCplt; |
| /* Set the DMA error callback */ |
| hhash->hdmain->XferErrorCallback = HASH_DMAError; |
| |
| /* Enable the DMA In DMA Stream */ |
| HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, (hhash->Init.KeySize%4 ? (hhash->Init.KeySize+3)/4:hhash->Init.KeySize/4)); |
| /* Enable DMA requests */ |
| HASH->CR |= (HASH_CR_DMAE); |
| |
| /* Process Unlocked */ |
| __HAL_UNLOCK(hhash); |
| |
| /* Return function status */ |
| return HAL_OK; |
| } |
| |
| /** |
| * @brief Initializes the HASH peripheral in HMAC SHA1 mode |
| * then enables DMA to control data transfer. |
| * @param hhash pointer to a HASH_HandleTypeDef structure that contains |
| * the configuration information for HASH module |
| * @param pInBuffer Pointer to the input buffer (buffer to be hashed). |
| * @param Size Length of the input buffer in bytes. |
| * If the Size is not multiple of 64 bytes, the padding is managed by hardware. |
| * @retval HAL status |
| */ |
| HAL_StatusTypeDef HAL_HMAC_SHA1_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) |
| { |
| uint32_t inputaddr = 0; |
| |
| /* Process Locked */ |
| __HAL_LOCK(hhash); |
| |
| /* Change the HASH state */ |
| hhash->State = HAL_HASH_STATE_BUSY; |
| |
| /* Save buffer pointer and size in handle */ |
| hhash->pHashInBuffPtr = pInBuffer; |
| hhash->HashBuffSize = Size; |
| hhash->HashInCount = 0; |
| |
| /* Check if initialization phase has already been performed */ |
| if(hhash->Phase == HAL_HASH_PHASE_READY) |
| { |
| /* Check if key size is greater than 64 bytes */ |
| if(hhash->Init.KeySize > 64) |
| { |
| /* Select the HMAC SHA1 mode */ |
| HASH->CR |= (HASH_ALGOSELECTION_SHA1 | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT); |
| } |
| else |
| { |
| /* Select the HMAC SHA1 mode */ |
| HASH->CR |= (HASH_ALGOSELECTION_SHA1 | HASH_ALGOMODE_HMAC | HASH_CR_INIT); |
| } |
| } |
| |
| /* Set the phase */ |
| hhash->Phase = HAL_HASH_PHASE_PROCESS; |
| |
| /* Configure the number of valid bits in last word of the message */ |
| __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize); |
| |
| /* Get the key address */ |
| inputaddr = (uint32_t)(hhash->Init.pKey); |
| |
| /* Set the HASH DMA transfer complete callback */ |
| hhash->hdmain->XferCpltCallback = HASH_DMAXferCplt; |
| /* Set the DMA error callback */ |
| hhash->hdmain->XferErrorCallback = HASH_DMAError; |
| |
| /* Enable the DMA In DMA Stream */ |
| HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, (hhash->Init.KeySize%4 ? (hhash->Init.KeySize+3)/4:hhash->Init.KeySize/4)); |
| /* Enable DMA requests */ |
| HASH->CR |= (HASH_CR_DMAE); |
| |
| /* Process Unlocked */ |
| __HAL_UNLOCK(hhash); |
| |
| /* Return function status */ |
| return HAL_OK; |
| } |
| |
| /** |
| * @} |
| */ |
| |
| /** @defgroup HASH_Exported_Functions_Group7 Peripheral State functions |
| * @brief Peripheral State functions. |
| * |
| @verbatim |
| =============================================================================== |
| ##### Peripheral State functions ##### |
| =============================================================================== |
| [..] |
| This subsection permits to get in run-time the status of the peripheral. |
| |
| @endverbatim |
| * @{ |
| */ |
| |
| /** |
| * @brief return the HASH state |
| * @param hhash pointer to a HASH_HandleTypeDef structure that contains |
| * the configuration information for HASH module |
| * @retval HAL state |
| */ |
| HAL_HASH_StateTypeDef HAL_HASH_GetState(HASH_HandleTypeDef *hhash) |
| { |
| return hhash->State; |
| } |
| |
| /** |
| * @} |
| */ |
| |
| /** |
| * @} |
| */ |
| |
| #endif /* HAL_HASH_MODULE_ENABLED */ |
| |
| /** |
| * @} |
| */ |
| #endif /* STM32F756xx || STM32F777xx || STM32F779xx */ |
| |
| /** |
| * @} |
| */ |
| |
| /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ |