--- /dev/null
+/**
+ ******************************************************************************
+ * @file stm32f4xx_hash_sha1.c
+ * @author MCD Application Team
+ * @version V1.0.0RC1
+ * @date 25-August-2011
+ * @brief This file provides high level functions to compute the HASH SHA1 and
+ * HMAC SHA1 Digest of an input message.
+ * It uses the stm32f4xx_hash.c/.h drivers to access the STM32F4xx HASH
+ * peripheral.
+ *
+ * @verbatim
+ *
+ * ===================================================================
+ * How to use this driver
+ * ===================================================================
+ * 1. Enable The HASH controller clock using
+ * RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_HASH, ENABLE); function.
+ *
+ * 2. Calculate the HASH SHA1 Digest using HASH_SHA1() function.
+ *
+ * 3. Calculate the HMAC SHA1 Digest using HMAC_SHA1() function.
+ *
+ * @endverbatim
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
+ * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
+ * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
+ * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
+ * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
+ * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+ *
+ * <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2>
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f4xx_hash.h"
+
+/** @addtogroup STM32F4xx_StdPeriph_Driver
+ * @{
+ */
+
+/** @defgroup HASH
+ * @brief HASH driver modules
+ * @{
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+#define SHA1BUSY_TIMEOUT ((uint32_t) 0x00010000)
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup HASH_Private_Functions
+ * @{
+ */
+
+/** @defgroup HASH_Group6 High Level SHA1 functions
+ * @brief High Level SHA1 Hash and HMAC functions
+ *
+@verbatim
+ ===============================================================================
+ High Level SHA1 Hash and HMAC functions
+ ===============================================================================
+
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Compute the HASH SHA1 digest.
+ * @param Input: pointer to the Input buffer to be treated.
+ * @param Ilen: length of the Input buffer.
+ * @param Output: the returned digest
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: digest computation done
+ * - ERROR: digest computation failed
+ */
+ErrorStatus HASH_SHA1(uint8_t *Input, uint32_t Ilen, uint8_t Output[20])
+{
+ HASH_InitTypeDef SHA1_HASH_InitStructure;
+ HASH_MsgDigest SHA1_MessageDigest;
+ __IO uint16_t nbvalidbitsdata = 0;
+ uint32_t i = 0;
+ __IO uint32_t counter = 0;
+ uint32_t busystatus = 0;
+ ErrorStatus status = SUCCESS;
+ uint32_t inputaddr = (uint32_t)Input;
+ uint32_t outputaddr = (uint32_t)Output;
+
+ /* Number of valid bits in last word of the Input data */
+ nbvalidbitsdata = 8 * (Ilen % 4);
+
+ /* HASH peripheral initialization */
+ HASH_DeInit();
+
+ /* HASH Configuration */
+ SHA1_HASH_InitStructure.HASH_AlgoSelection = HASH_AlgoSelection_SHA1;
+ SHA1_HASH_InitStructure.HASH_AlgoMode = HASH_AlgoMode_HASH;
+ SHA1_HASH_InitStructure.HASH_DataType = HASH_DataType_8b;
+ HASH_Init(&SHA1_HASH_InitStructure);
+
+ /* Configure the number of valid bits in last word of the data */
+ HASH_SetLastWordValidBitsNbr(nbvalidbitsdata);
+
+ /* Write the Input block in the IN FIFO */
+ for(i=0; i<Ilen; i+=4)
+ {
+ HASH_DataIn(*(uint32_t*)inputaddr);
+ inputaddr+=4;
+ }
+
+ /* Start the HASH processor */
+ HASH_StartDigest();
+
+ /* wait until the Busy flag is RESET */
+ do
+ {
+ busystatus = HASH_GetFlagStatus(HASH_FLAG_BUSY);
+ counter++;
+ }while ((counter != SHA1BUSY_TIMEOUT) && (busystatus != RESET));
+
+ if (busystatus != RESET)
+ {
+ status = ERROR;
+ }
+ else
+ {
+ /* Read the message digest */
+ HASH_GetDigest(&SHA1_MessageDigest);
+ *(uint32_t*)(outputaddr) = __REV(SHA1_MessageDigest.Data[0]);
+ outputaddr+=4;
+ *(uint32_t*)(outputaddr) = __REV(SHA1_MessageDigest.Data[1]);
+ outputaddr+=4;
+ *(uint32_t*)(outputaddr) = __REV(SHA1_MessageDigest.Data[2]);
+ outputaddr+=4;
+ *(uint32_t*)(outputaddr) = __REV(SHA1_MessageDigest.Data[3]);
+ outputaddr+=4;
+ *(uint32_t*)(outputaddr) = __REV(SHA1_MessageDigest.Data[4]);
+ }
+ return status;
+}
+
+/**
+ * @brief Compute the HMAC SHA1 digest.
+ * @param Key: pointer to the Key used for HMAC.
+ * @param Keylen: length of the Key used for HMAC.
+ * @param Input: pointer to the Input buffer to be treated.
+ * @param Ilen: length of the Input buffer.
+ * @param Output: the returned digest
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: digest computation done
+ * - ERROR: digest computation failed
+ */
+ErrorStatus HMAC_SHA1(uint8_t *Key, uint32_t Keylen, uint8_t *Input,
+ uint32_t Ilen, uint8_t Output[20])
+{
+ HASH_InitTypeDef SHA1_HASH_InitStructure;
+ HASH_MsgDigest SHA1_MessageDigest;
+ __IO uint16_t nbvalidbitsdata = 0;
+ __IO uint16_t nbvalidbitskey = 0;
+ uint32_t i = 0;
+ __IO uint32_t counter = 0;
+ uint32_t busystatus = 0;
+ ErrorStatus status = SUCCESS;
+ uint32_t keyaddr = (uint32_t)Key;
+ uint32_t inputaddr = (uint32_t)Input;
+ uint32_t outputaddr = (uint32_t)Output;
+
+ /* Number of valid bits in last word of the Input data */
+ nbvalidbitsdata = 8 * (Ilen % 4);
+
+ /* Number of valid bits in last word of the Key */
+ nbvalidbitskey = 8 * (Keylen % 4);
+
+ /* HASH peripheral initialization */
+ HASH_DeInit();
+
+ /* HASH Configuration */
+ SHA1_HASH_InitStructure.HASH_AlgoSelection = HASH_AlgoSelection_SHA1;
+ SHA1_HASH_InitStructure.HASH_AlgoMode = HASH_AlgoMode_HMAC;
+ SHA1_HASH_InitStructure.HASH_DataType = HASH_DataType_8b;
+ if(Keylen > 64)
+ {
+ /* HMAC long Key */
+ SHA1_HASH_InitStructure.HASH_HMACKeyType = HASH_HMACKeyType_LongKey;
+ }
+ else
+ {
+ /* HMAC short Key */
+ SHA1_HASH_InitStructure.HASH_HMACKeyType = HASH_HMACKeyType_ShortKey;
+ }
+ HASH_Init(&SHA1_HASH_InitStructure);
+
+ /* Configure the number of valid bits in last word of the Key */
+ HASH_SetLastWordValidBitsNbr(nbvalidbitskey);
+
+ /* Write the Key */
+ for(i=0; i<Keylen; i+=4)
+ {
+ HASH_DataIn(*(uint32_t*)keyaddr);
+ keyaddr+=4;
+ }
+
+ /* Start the HASH processor */
+ HASH_StartDigest();
+
+ /* wait until the Busy flag is RESET */
+ do
+ {
+ busystatus = HASH_GetFlagStatus(HASH_FLAG_BUSY);
+ counter++;
+ }while ((counter != SHA1BUSY_TIMEOUT) && (busystatus != RESET));
+
+ if (busystatus != RESET)
+ {
+ status = ERROR;
+ }
+ else
+ {
+ /* Configure the number of valid bits in last word of the Input data */
+ HASH_SetLastWordValidBitsNbr(nbvalidbitsdata);
+
+ /* Write the Input block in the IN FIFO */
+ for(i=0; i<Ilen; i+=4)
+ {
+ HASH_DataIn(*(uint32_t*)inputaddr);
+ inputaddr+=4;
+ }
+
+ /* Start the HASH processor */
+ HASH_StartDigest();
+
+
+ /* wait until the Busy flag is RESET */
+ counter =0;
+ do
+ {
+ busystatus = HASH_GetFlagStatus(HASH_FLAG_BUSY);
+ counter++;
+ }while ((counter != SHA1BUSY_TIMEOUT) && (busystatus != RESET));
+
+ if (busystatus != RESET)
+ {
+ status = ERROR;
+ }
+ else
+ {
+ /* Configure the number of valid bits in last word of the Key */
+ HASH_SetLastWordValidBitsNbr(nbvalidbitskey);
+
+ /* Write the Key */
+ keyaddr = (uint32_t)Key;
+ for(i=0; i<Keylen; i+=4)
+ {
+ HASH_DataIn(*(uint32_t*)keyaddr);
+ keyaddr+=4;
+ }
+
+ /* Start the HASH processor */
+ HASH_StartDigest();
+
+ /* wait until the Busy flag is RESET */
+ counter =0;
+ do
+ {
+ busystatus = HASH_GetFlagStatus(HASH_FLAG_BUSY);
+ counter++;
+ }while ((counter != SHA1BUSY_TIMEOUT) && (busystatus != RESET));
+
+ if (busystatus != RESET)
+ {
+ status = ERROR;
+ }
+ else
+ {
+ /* Read the message digest */
+ HASH_GetDigest(&SHA1_MessageDigest);
+ *(uint32_t*)(outputaddr) = __REV(SHA1_MessageDigest.Data[0]);
+ outputaddr+=4;
+ *(uint32_t*)(outputaddr) = __REV(SHA1_MessageDigest.Data[1]);
+ outputaddr+=4;
+ *(uint32_t*)(outputaddr) = __REV(SHA1_MessageDigest.Data[2]);
+ outputaddr+=4;
+ *(uint32_t*)(outputaddr) = __REV(SHA1_MessageDigest.Data[3]);
+ outputaddr+=4;
+ *(uint32_t*)(outputaddr) = __REV(SHA1_MessageDigest.Data[4]);
+ }
+ }
+ }
+ return status;
+}
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/