| /** |
| ****************************************************************************** |
| * @file stm32f7xx_hal_hash_ex.c |
| * @author MCD Application Team |
| * @brief HASH HAL Extension module driver. |
| * This file provides firmware functions to manage the following |
| * functionalities of HASH peripheral: |
| * + Extended HASH processing functions based on SHA224 Algorithm |
| * + Extended HASH processing functions based on SHA256 Algorithm |
| * |
| @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_HMACEx_SHA224_Start()) |
| (+++) 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_HMACEx_SH224_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: 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_HASHEx_SHA224_Start() |
| (##) Interrupt mode: encryption and decryption APIs are not blocking functions |
| i.e. they process the data under interrupt |
| e.g. HAL_HASHEx_SHA224_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_HASHEx_SHA224_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_HASHEx_SHA224_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_HASHEx_SHA224_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_HASHEx_SHA224_Start_DMA(). |
| After that, call the finish function in order to get the digest value |
| e.g. HAL_HASHEx_SHA224_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 HASHEx HASHEx |
| * @brief HASH Extension HAL module driver. |
| * @{ |
| */ |
| |
| #ifdef HAL_HASH_MODULE_ENABLED |
| |
| /* Private typedef -----------------------------------------------------------*/ |
| /* Private define ------------------------------------------------------------*/ |
| /* Private macro -------------------------------------------------------------*/ |
| /* Private variables ---------------------------------------------------------*/ |
| /* Private function prototypes -----------------------------------------------*/ |
| /** @addtogroup HASHEx_Private_Functions |
| * @{ |
| */ |
| static void HASHEx_DMAXferCplt(DMA_HandleTypeDef *hdma); |
| static void HASHEx_WriteData(uint8_t *pInBuffer, uint32_t Size); |
| static void HASHEx_GetDigest(uint8_t *pMsgDigest, uint8_t Size); |
| static void HASHEx_DMAError(DMA_HandleTypeDef *hdma); |
| /** |
| * @} |
| */ |
| |
| /* Private functions ---------------------------------------------------------*/ |
| |
| /** @addtogroup HASHEx_Private_Functions |
| * @{ |
| */ |
| |
| /** |
| * @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 HASHEx_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 HASHEx_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; |
| } |
| } |
| |
| /** |
| * @brief DMA HASH Input Data complete callback. |
| * @param hdma DMA handle |
| * @retval None |
| */ |
| static void HASHEx_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 = HASHEx_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 HASHEx_DMAError(DMA_HandleTypeDef *hdma) |
| { |
| HASH_HandleTypeDef* hhash = ( HASH_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; |
| hhash->State= HAL_HASH_STATE_READY; |
| HAL_HASH_ErrorCallback(hhash); |
| } |
| |
| /** |
| * @} |
| */ |
| |
| /* Exported functions --------------------------------------------------------*/ |
| /** @addtogroup HASHEx_Exported_Functions |
| * @{ |
| */ |
| |
| /** @defgroup HASHEx_Group1 HASH processing functions |
| * @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: |
| (+) SHA224 |
| (+) SHA256 |
| |
| @endverbatim |
| * @{ |
| */ |
| |
| /** |
| * @brief Initializes the HASH peripheral in SHA224 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 28 bytes. |
| * @param Timeout Specify Timeout value |
| * @retval HAL status |
| */ |
| HAL_StatusTypeDef HAL_HASHEx_SHA224_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 SHA224 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_SHA224 | 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 */ |
| HASHEx_WriteData(pInBuffer, Size); |
| |
| /* Start the digest calculation */ |
| __HAL_HASH_START_DIGEST(); |
| |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| |
| while((HASH->SR & HASH_FLAG_BUSY) == 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 */ |
| HASHEx_GetDigest(pOutBuffer, 28); |
| |
| /* 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 SHA256 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 32 bytes. |
| * @param Timeout Specify Timeout value |
| * @retval HAL status |
| */ |
| HAL_StatusTypeDef HAL_HASHEx_SHA256_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 SHA256 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_SHA256 | 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 */ |
| HASHEx_WriteData(pInBuffer, Size); |
| |
| /* Start the digest calculation */ |
| __HAL_HASH_START_DIGEST(); |
| |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| |
| while((HASH->SR & HASH_FLAG_BUSY) == 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 */ |
| HASHEx_GetDigest(pOutBuffer, 32); |
| |
| /* 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 SHA224 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. |
| * @retval HAL status |
| */ |
| HAL_StatusTypeDef HAL_HASHEx_SHA224_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 SHA224 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_SHA224 | 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 */ |
| HASHEx_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 SHA256 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. |
| * @retval HAL status |
| */ |
| HAL_StatusTypeDef HAL_HASHEx_SHA256_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 SHA256 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_SHA256 | 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 */ |
| HASHEx_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 HASHEx_Group2 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: |
| (+) SHA224 |
| (+) SHA256 |
| |
| @endverbatim |
| * @{ |
| */ |
| |
| /** |
| * @brief Initializes the HASH peripheral in HMAC SHA224 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_HMACEx_SHA224_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 SHA224 mode */ |
| HASH->CR |= (HASH_ALGOSELECTION_SHA224 | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT); |
| } |
| else |
| { |
| /* Select the HMAC SHA224 mode */ |
| HASH->CR |= (HASH_ALGOSELECTION_SHA224 | 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 */ |
| HASHEx_WriteData(hhash->Init.pKey, hhash->Init.KeySize); |
| |
| /* Start the digest calculation */ |
| __HAL_HASH_START_DIGEST(); |
| |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| |
| while((HASH->SR & HASH_FLAG_BUSY) == 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 */ |
| HASHEx_WriteData(pInBuffer, Size); |
| |
| /* Start the digest calculation */ |
| __HAL_HASH_START_DIGEST(); |
| |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| |
| while((HASH->SR & HASH_FLAG_BUSY) == 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 */ |
| HASHEx_WriteData(hhash->Init.pKey, hhash->Init.KeySize); |
| |
| /* Start the digest calculation */ |
| __HAL_HASH_START_DIGEST(); |
| |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| |
| while((HASH->SR & HASH_FLAG_BUSY) == 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 */ |
| HASHEx_GetDigest(pOutBuffer, 28); |
| |
| /* 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 SHA256 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_HMACEx_SHA256_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 SHA256 mode */ |
| HASH->CR |= (HASH_ALGOSELECTION_SHA256 | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY); |
| } |
| else |
| { |
| /* Select the HMAC SHA256 mode */ |
| HASH->CR |= (HASH_ALGOSELECTION_SHA256 | HASH_ALGOMODE_HMAC); |
| } |
| /* 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; |
| } |
| |
| /* 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 */ |
| HASHEx_WriteData(hhash->Init.pKey, hhash->Init.KeySize); |
| |
| /* Start the digest calculation */ |
| __HAL_HASH_START_DIGEST(); |
| |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| |
| while((HASH->SR & HASH_FLAG_BUSY) == 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 */ |
| HASHEx_WriteData(pInBuffer, Size); |
| |
| /* Start the digest calculation */ |
| __HAL_HASH_START_DIGEST(); |
| |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| |
| while((HASH->SR & HASH_FLAG_BUSY) == 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 */ |
| HASHEx_WriteData(hhash->Init.pKey, hhash->Init.KeySize); |
| |
| /* Start the digest calculation */ |
| __HAL_HASH_START_DIGEST(); |
| |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| |
| while((HASH->SR & HASH_FLAG_BUSY) == 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 */ |
| HASHEx_GetDigest(pOutBuffer, 32); |
| |
| /* Change the HASH state */ |
| hhash->State = HAL_HASH_STATE_READY; |
| |
| /* Process Unlocked */ |
| __HAL_UNLOCK(hhash); |
| |
| /* Return function status */ |
| return HAL_OK; |
| } |
| |
| /** |
| * @} |
| */ |
| |
| /** @defgroup HASHEx_Group3 HASH processing functions using interrupt mode |
| * @brief processing functions using interrupt mode. |
| * |
| @verbatim |
| =============================================================================== |
| ##### HASH processing using interrupt functions ##### |
| =============================================================================== |
| [..] This section provides functions allowing to calculate in interrupt mode |
| the hash value using one of the following algorithms: |
| (+) SHA224 |
| (+) SHA256 |
| |
| @endverbatim |
| * @{ |
| */ |
| |
| /** |
| * @brief Initializes the HASH peripheral in SHA224 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_HASHEx_SHA224_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer) |
| { |
| uint32_t inputaddr; |
| 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 SHA224 mode */ |
| HASH->CR |= HASH_ALGOSELECTION_SHA224; |
| /* 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)) |
| { |
| /* Read the message digest */ |
| HASHEx_GetDigest(hhash->pHashOutBuffPtr, 28); |
| 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 SHA256 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_HASHEx_SHA256_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer) |
| { |
| uint32_t inputaddr; |
| 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 SHA256 mode */ |
| HASH->CR |= HASH_ALGOSELECTION_SHA256; |
| /* 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)) |
| { |
| /* Read the message digest */ |
| HASHEx_GetDigest(hhash->pHashOutBuffPtr, 32); |
| 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_HASHEx_IRQHandler(HASH_HandleTypeDef *hhash) |
| { |
| switch(HASH->CR & HASH_CR_ALGO) |
| { |
| |
| case HASH_ALGOSELECTION_SHA224: |
| HAL_HASHEx_SHA224_Start_IT(hhash, NULL, 0, NULL); |
| break; |
| |
| case HASH_ALGOSELECTION_SHA256: |
| HAL_HASHEx_SHA256_Start_IT(hhash, NULL, 0, NULL); |
| break; |
| |
| default: |
| break; |
| } |
| } |
| |
| /** |
| * @} |
| */ |
| |
| /** @defgroup HASHEx_Group4 HASH processing functions using DMA mode |
| * @brief processing functions using DMA mode. |
| * |
| @verbatim |
| =============================================================================== |
| ##### HASH processing using DMA functions ##### |
| =============================================================================== |
| [..] This section provides functions allowing to calculate in DMA mode |
| the hash value using one of the following algorithms: |
| (+) SHA224 |
| (+) SHA256 |
| |
| @endverbatim |
| * @{ |
| */ |
| |
| |
| /** |
| * @brief Initializes the HASH peripheral in SHA224 mode then enables DMA to |
| control data transfer. Use HAL_HASH_SHA224_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_HASHEx_SHA224_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 SHA224 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_SHA224 | 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 = HASHEx_DMAXferCplt; |
| /* Set the DMA error callback */ |
| hhash->hdmain->XferErrorCallback = HASHEx_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 SHA224 |
| * @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 28 bytes. |
| * @param Timeout Timeout value |
| * @retval HAL status |
| */ |
| HAL_StatusTypeDef HAL_HASHEx_SHA224_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 */ |
| HASHEx_GetDigest(pOutBuffer, 28); |
| |
| /* 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 SHA256 mode then enables DMA to |
| control data transfer. Use HAL_HASH_SHA256_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_HASHEx_SHA256_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 SHA256 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_SHA256 | 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 = HASHEx_DMAXferCplt; |
| /* Set the DMA error callback */ |
| hhash->hdmain->XferErrorCallback = HASHEx_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 UnLock */ |
| __HAL_UNLOCK(hhash); |
| |
| /* Return function status */ |
| return HAL_OK; |
| } |
| |
| /** |
| * @brief Returns the computed digest in SHA256. |
| * @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 32 bytes. |
| * @param Timeout Timeout value |
| * @retval HAL status |
| */ |
| HAL_StatusTypeDef HAL_HASHEx_SHA256_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 */ |
| HASHEx_GetDigest(pOutBuffer, 32); |
| |
| /* Change HASH peripheral state */ |
| hhash->State = HAL_HASH_STATE_READY; |
| |
| /* Process Unlocked */ |
| __HAL_UNLOCK(hhash); |
| |
| /* Return function status */ |
| return HAL_OK; |
| } |
| |
| |
| /** |
| * @} |
| */ |
| /** @defgroup HASHEx_Group5 HMAC processing functions using DMA mode |
| * @brief HMAC processing functions using DMA mode . |
| * |
| @verbatim |
| =============================================================================== |
| ##### HMAC processing using DMA functions ##### |
| =============================================================================== |
| [..] This section provides functions allowing to calculate in DMA mode |
| the HMAC value using one of the following algorithms: |
| (+) SHA224 |
| (+) SHA256 |
| |
| @endverbatim |
| * @{ |
| */ |
| |
| /** |
| * @brief Initializes the HASH peripheral in HMAC SHA224 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_HMACEx_SHA224_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) |
| { |
| uint32_t inputaddr; |
| |
| /* 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 SHA224 mode */ |
| HASH->CR |= (HASH_ALGOSELECTION_SHA224 | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT); |
| } |
| else |
| { |
| /* Select the HMAC SHA224 mode */ |
| HASH->CR |= (HASH_ALGOSELECTION_SHA224 | 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 = HASHEx_DMAXferCplt; |
| /* Set the DMA error callback */ |
| hhash->hdmain->XferErrorCallback = HASHEx_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 SHA256 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_HMACEx_SHA256_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) |
| { |
| uint32_t inputaddr; |
| |
| /* 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 SHA256 mode */ |
| HASH->CR |= (HASH_ALGOSELECTION_SHA256 | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY); |
| } |
| else |
| { |
| /* Select the HMAC SHA256 mode */ |
| HASH->CR |= (HASH_ALGOSELECTION_SHA256 | HASH_ALGOMODE_HMAC); |
| } |
| /* 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; |
| } |
| |
| /* 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 = HASHEx_DMAXferCplt; |
| /* Set the DMA error callback */ |
| hhash->hdmain->XferErrorCallback = HASHEx_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; |
| } |
| |
| /** |
| * @} |
| */ |
| |
| /** |
| * @} |
| */ |
| #endif /* HAL_HASH_MODULE_ENABLED */ |
| |
| /** |
| * @} |
| */ |
| #endif /* STM32F756xx || STM32F777xx || STM32F779xx */ |
| |
| /** |
| * @} |
| */ |
| |
| /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ |