mbed library sources

Dependents:   bare

Fork of mbed-src by mbed official

Revision:
87:085cde657901
Child:
106:ced8cbb51063
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/targets/cmsis/TARGET_STM/TARGET_NUCLEO_F401RE/stm32f4xx_hal_hash_ex.c	Sat Feb 08 19:45:06 2014 +0000
@@ -0,0 +1,1598 @@
+/**
+  ******************************************************************************
+  * @file    stm32f4xx_hal_hash_ex.c
+  * @author  MCD Application Team
+  * @version V1.0.0RC2
+  * @date    04-February-2014
+  * @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 __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>&copy; COPYRIGHT(c) 2014 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 "stm32f4xx_hal.h"
+
+/** @addtogroup STM32F4xx_HAL_Driver
+  * @{
+  */
+
+/** @defgroup HASHEx 
+  * @brief HASH Extension HAL module driver.
+  * @{
+  */
+
+#ifdef HAL_HASH_MODULE_ENABLED
+
+#if defined(STM32F437xx) || defined(STM32F439xx)
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+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 ---------------------------------------------------------*/
+
+/** @defgroup HASHEx_Private_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: HASH handle
+  * @param  pInBuffer: Pointer to the input buffer (buffer to be hashed).
+  * @param  pOutBuffer: Pointer to the output buffer (hashed buffer).
+  * @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 timeout = 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 timeout */
+  timeout = HAL_GetTick() + Timeout;
+  
+  while((HASH->SR & HASH_FLAG_BUSY) == HASH_FLAG_BUSY)
+  {
+    /* Check for the Timeout */
+    if(Timeout != HAL_MAX_DELAY)
+    {
+      if(HAL_GetTick() >= 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: HASH handle
+  * @param  pInBuffer: Pointer to the input buffer (buffer to be hashed).
+  * @param  pOutBuffer: Pointer to the output buffer (hashed buffer).  
+  * @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 timeout = 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 timeout */
+  timeout = HAL_GetTick() + Timeout;
+  
+  while((HASH->SR & HASH_FLAG_BUSY) == HASH_FLAG_BUSY)
+  {
+    /* Check for the Timeout */
+    if(Timeout != HAL_MAX_DELAY)
+    {
+      if(HAL_GetTick() >= 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: HASH handle
+  * @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: HASH handle
+  * @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: HASH handle
+  * @param  pInBuffer: Pointer to the input buffer (buffer to be hashed).
+  * @param  pOutBuffer: Pointer to the output buffer (hashed buffer).  
+  * @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_HMACEx_SHA224_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout)
+{
+  uint32_t timeout = 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_HMACKeyType_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 timeout */
+  timeout = HAL_GetTick() + Timeout;
+  
+  while((HASH->SR & HASH_FLAG_BUSY) == HASH_FLAG_BUSY)
+  {
+    /* Check for the Timeout */
+    if(Timeout != HAL_MAX_DELAY)
+    {
+      if(HAL_GetTick() >= 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 timeout */
+  timeout = HAL_GetTick() + Timeout;
+  
+  while((HASH->SR & HASH_FLAG_BUSY) == HASH_FLAG_BUSY)
+  {
+    /* Check for the Timeout */
+    if(Timeout != HAL_MAX_DELAY)
+    {
+      if(HAL_GetTick() >= 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 timeout */
+  timeout = HAL_GetTick() + Timeout;
+  
+  while((HASH->SR & HASH_FLAG_BUSY) == HASH_FLAG_BUSY)
+  {
+    /* Check for the Timeout */
+    if(Timeout != HAL_MAX_DELAY)
+    {
+      if(HAL_GetTick() >= 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: HASH handle
+  * @param  pInBuffer: Pointer to the input buffer (buffer to be hashed).
+  * @param  pOutBuffer: Pointer to the output buffer (hashed buffer).  
+  * @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_HMACEx_SHA256_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout)
+{
+  uint32_t timeout = 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_HMACKeyType_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 timeout */
+  timeout = HAL_GetTick() + Timeout;
+  
+  while((HASH->SR & HASH_FLAG_BUSY) == HASH_FLAG_BUSY)
+  {
+    /* Check for the Timeout */
+    if(Timeout != HAL_MAX_DELAY)
+    {
+      if(HAL_GetTick() >= 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 timeout */
+  timeout = HAL_GetTick() + Timeout;
+  
+  while((HASH->SR & HASH_FLAG_BUSY) == HASH_FLAG_BUSY)
+  {
+    /* Check for the Timeout */
+    if(Timeout != HAL_MAX_DELAY)
+    {
+      if(HAL_GetTick() >= 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 timeout */
+  timeout = HAL_GetTick() + Timeout;
+  
+  while((HASH->SR & HASH_FLAG_BUSY) == HASH_FLAG_BUSY)
+  {
+    /* Check for the Timeout */
+    if(Timeout != HAL_MAX_DELAY)
+    {
+      if(HAL_GetTick() >= 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: HASH handle
+  * @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->HashITCounter == 0)
+  {
+    hhash->HashITCounter = 1;
+  }
+  else
+  {
+    hhash->HashITCounter = 0;
+  }
+  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;
+    }
+    
+    /* 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);
+    }
+  }
+  if(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))
+  {
+    if(hhash->HashInCount > 64)
+    {
+      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 -= 64;
+        }
+      }
+      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);
+      }
+      
+      /* 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: HASH handle
+  * @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->HashITCounter == 0)
+  {
+    hhash->HashITCounter = 1;
+  }
+  else
+  {
+    hhash->HashITCounter = 0;
+  }
+  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;
+    }
+    
+    /* 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);
+    }
+  }
+  if(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))
+  {
+    if(hhash->HashInCount > 64)
+    {
+      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 -= 64;
+        }
+      }
+      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);
+      }
+      
+      /* 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: hash handle
+  * @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: HASH handle
+  * @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.
+  * @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: HASH handle
+  * @param  pOutBuffer: Pointer to the computed digest. Its size must be 28 bytes.
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_HASHEx_SHA224_Finish(HASH_HandleTypeDef *hhash, uint8_t* pOutBuffer, uint32_t Timeout)
+{
+  uint32_t timeout = 0;   
+  
+  /* Process Locked */
+  __HAL_LOCK(hhash);
+  
+  /* Change HASH peripheral state */
+  hhash->State = HAL_HASH_STATE_BUSY;
+  
+  /* Get timeout */
+  timeout = HAL_GetTick() + Timeout;
+  
+  while(HAL_IS_BIT_CLR(HASH->SR, HASH_FLAG_DCIS))
+  {
+    /* Check for the Timeout */
+    if(Timeout != HAL_MAX_DELAY)
+    {
+      if(HAL_GetTick() >= 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: HASH handle
+  * @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_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: HASH handle
+  * @param  pOutBuffer: Pointer to the computed digest. Its size must be 32 bytes.
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_HASHEx_SHA256_Finish(HASH_HandleTypeDef *hhash, uint8_t* pOutBuffer, uint32_t Timeout)
+{
+  uint32_t timeout = 0;   
+  
+   /* Process Locked */
+  __HAL_LOCK(hhash);
+  
+  /* Change HASH peripheral state */
+  hhash->State = HAL_HASH_STATE_BUSY;
+  
+  /* Get timeout */
+  timeout = HAL_GetTick() + Timeout;
+  
+  while(HAL_IS_BIT_CLR(HASH->SR, HASH_FLAG_DCIS))
+  {
+    /* Check for the Timeout */
+    if(Timeout != HAL_MAX_DELAY)
+    {
+      if(HAL_GetTick() >= 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: HASH handle
+  * @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_HMACKeyType_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: HASH handle
+  * @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_HMACKeyType_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;
+}
+
+/**
+  * @}
+  */
+
+/**
+  * @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 */
+      HASH->STR |= 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);
+}
+
+
+/**
+  * @}
+  */
+#endif /* STM32F437xx || STM32F439xx */
+
+#endif /* HAL_HASH_MODULE_ENABLED */
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/