/** | |
****************************************************************************** | |
* @file stm32f7xx_hal_hash.c | |
* @author MCD Application Team | |
* @version V1.1.1 | |
* @date 01-July-2016 | |
* @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) 2016 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****/ |