2 ******************************************************************************
3 * @file stm32f4xx_hash_md5.c
4 * @author MCD Application Team
7 * @brief This file provides high level functions to compute the HASH MD5 and
8 * HMAC MD5 Digest of an input message.
9 * It uses the stm32f4xx_hash.c/.h drivers to access the STM32F4xx HASH
14 * ===================================================================
15 * How to use this driver
16 * ===================================================================
17 * 1. Enable The HASH controller clock using
18 * RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_HASH, ENABLE); function.
20 * 2. Calculate the HASH MD5 Digest using HASH_MD5() function.
22 * 3. Calculate the HMAC MD5 Digest using HMAC_MD5() function.
26 ******************************************************************************
29 * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
30 * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
31 * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
32 * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
33 * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
34 * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
36 * <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2>
37 ******************************************************************************
40 /* Includes ------------------------------------------------------------------*/
41 #include "stm32f4xx_hash.h"
43 /** @addtogroup STM32F4xx_StdPeriph_Driver
48 * @brief HASH driver modules
52 /* Private typedef -----------------------------------------------------------*/
53 /* Private define ------------------------------------------------------------*/
54 #define MD5BUSY_TIMEOUT ((uint32_t) 0x00010000)
56 /* Private macro -------------------------------------------------------------*/
57 /* Private variables ---------------------------------------------------------*/
58 /* Private function prototypes -----------------------------------------------*/
59 /* Private functions ---------------------------------------------------------*/
61 /** @defgroup HASH_Private_Functions
65 /** @defgroup HASH_Group7 High Level MD5 functions
66 * @brief High Level MD5 Hash and HMAC functions
69 ===============================================================================
70 High Level MD5 Hash and HMAC functions
71 ===============================================================================
79 * @brief Compute the HASH MD5 digest.
80 * @param Input: pointer to the Input buffer to be treated.
81 * @param Ilen: length of the Input buffer.
82 * @param Output: the returned digest
83 * @retval An ErrorStatus enumeration value:
84 * - SUCCESS: digest computation done
85 * - ERROR: digest computation failed
87 ErrorStatus HASH_MD5(uint8_t *Input, uint32_t Ilen, uint8_t Output[16])
89 HASH_InitTypeDef MD5_HASH_InitStructure;
90 HASH_MsgDigest MD5_MessageDigest;
91 __IO uint16_t nbvalidbitsdata = 0;
93 __IO uint32_t counter = 0;
94 uint32_t busystatus = 0;
95 ErrorStatus status = SUCCESS;
96 uint32_t inputaddr = (uint32_t)Input;
97 uint32_t outputaddr = (uint32_t)Output;
100 /* Number of valid bits in last word of the Input data */
101 nbvalidbitsdata = 8 * (Ilen % 4);
103 /* HASH peripheral initialization */
106 /* HASH Configuration */
107 MD5_HASH_InitStructure.HASH_AlgoSelection = HASH_AlgoSelection_MD5;
108 MD5_HASH_InitStructure.HASH_AlgoMode = HASH_AlgoMode_HASH;
109 MD5_HASH_InitStructure.HASH_DataType = HASH_DataType_8b;
110 HASH_Init(&MD5_HASH_InitStructure);
112 /* Configure the number of valid bits in last word of the data */
113 HASH_SetLastWordValidBitsNbr(nbvalidbitsdata);
115 /* Write the Input block in the IN FIFO */
116 for(i=0; i<Ilen; i+=4)
118 HASH_DataIn(*(uint32_t*)inputaddr);
122 /* Start the HASH processor */
125 /* wait until the Busy flag is RESET */
128 busystatus = HASH_GetFlagStatus(HASH_FLAG_BUSY);
130 }while ((counter != MD5BUSY_TIMEOUT) && (busystatus != RESET));
132 if (busystatus != RESET)
138 /* Read the message digest */
139 HASH_GetDigest(&MD5_MessageDigest);
140 *(uint32_t*)(outputaddr) = __REV(MD5_MessageDigest.Data[0]);
142 *(uint32_t*)(outputaddr) = __REV(MD5_MessageDigest.Data[1]);
144 *(uint32_t*)(outputaddr) = __REV(MD5_MessageDigest.Data[2]);
146 *(uint32_t*)(outputaddr) = __REV(MD5_MessageDigest.Data[3]);
152 * @brief Compute the HMAC MD5 digest.
153 * @param Key: pointer to the Key used for HMAC.
154 * @param Keylen: length of the Key used for HMAC.
155 * @param Input: pointer to the Input buffer to be treated.
156 * @param Ilen: length of the Input buffer.
157 * @param Output: the returned digest
158 * @retval An ErrorStatus enumeration value:
159 * - SUCCESS: digest computation done
160 * - ERROR: digest computation failed
162 ErrorStatus HMAC_MD5(uint8_t *Key, uint32_t Keylen, uint8_t *Input,
163 uint32_t Ilen, uint8_t Output[16])
165 HASH_InitTypeDef MD5_HASH_InitStructure;
166 HASH_MsgDigest MD5_MessageDigest;
167 __IO uint16_t nbvalidbitsdata = 0;
168 __IO uint16_t nbvalidbitskey = 0;
170 __IO uint32_t counter = 0;
171 uint32_t busystatus = 0;
172 ErrorStatus status = SUCCESS;
173 uint32_t keyaddr = (uint32_t)Key;
174 uint32_t inputaddr = (uint32_t)Input;
175 uint32_t outputaddr = (uint32_t)Output;
177 /* Number of valid bits in last word of the Input data */
178 nbvalidbitsdata = 8 * (Ilen % 4);
180 /* Number of valid bits in last word of the Key */
181 nbvalidbitskey = 8 * (Keylen % 4);
183 /* HASH peripheral initialization */
186 /* HASH Configuration */
187 MD5_HASH_InitStructure.HASH_AlgoSelection = HASH_AlgoSelection_MD5;
188 MD5_HASH_InitStructure.HASH_AlgoMode = HASH_AlgoMode_HMAC;
189 MD5_HASH_InitStructure.HASH_DataType = HASH_DataType_8b;
193 MD5_HASH_InitStructure.HASH_HMACKeyType = HASH_HMACKeyType_LongKey;
198 MD5_HASH_InitStructure.HASH_HMACKeyType = HASH_HMACKeyType_ShortKey;
200 HASH_Init(&MD5_HASH_InitStructure);
202 /* Configure the number of valid bits in last word of the Key */
203 HASH_SetLastWordValidBitsNbr(nbvalidbitskey);
206 for(i=0; i<Keylen; i+=4)
208 HASH_DataIn(*(uint32_t*)keyaddr);
212 /* Start the HASH processor */
215 /* wait until the Busy flag is RESET */
218 busystatus = HASH_GetFlagStatus(HASH_FLAG_BUSY);
220 }while ((counter != MD5BUSY_TIMEOUT) && (busystatus != RESET));
222 if (busystatus != RESET)
228 /* Configure the number of valid bits in last word of the Input data */
229 HASH_SetLastWordValidBitsNbr(nbvalidbitsdata);
231 /* Write the Input block in the IN FIFO */
232 for(i=0; i<Ilen; i+=4)
234 HASH_DataIn(*(uint32_t*)inputaddr);
238 /* Start the HASH processor */
241 /* wait until the Busy flag is RESET */
245 busystatus = HASH_GetFlagStatus(HASH_FLAG_BUSY);
247 }while ((counter != MD5BUSY_TIMEOUT) && (busystatus != RESET));
249 if (busystatus != RESET)
255 /* Configure the number of valid bits in last word of the Key */
256 HASH_SetLastWordValidBitsNbr(nbvalidbitskey);
259 keyaddr = (uint32_t)Key;
260 for(i=0; i<Keylen; i+=4)
262 HASH_DataIn(*(uint32_t*)keyaddr);
266 /* Start the HASH processor */
269 /* wait until the Busy flag is RESET */
273 busystatus = HASH_GetFlagStatus(HASH_FLAG_BUSY);
275 }while ((counter != MD5BUSY_TIMEOUT) && (busystatus != RESET));
277 if (busystatus != RESET)
283 /* Read the message digest */
284 HASH_GetDigest(&MD5_MessageDigest);
285 *(uint32_t*)(outputaddr) = __REV(MD5_MessageDigest.Data[0]);
287 *(uint32_t*)(outputaddr) = __REV(MD5_MessageDigest.Data[1]);
289 *(uint32_t*)(outputaddr) = __REV(MD5_MessageDigest.Data[2]);
291 *(uint32_t*)(outputaddr) = __REV(MD5_MessageDigest.Data[3]);
313 /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/