1 /**
2 ******************************************************************************
3 * @file stm32f4xx_hash_md5.c
4 * @author MCD Application Team
5 * @version V1.5.1
6 * @date 22-May-2015
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
10 * peripheral.
11 *
12 @verbatim
13 ===================================================================
14 ##### How to use this driver #####
15 ===================================================================
16 [..]
17 (#) Enable The HASH controller clock using
18 RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_HASH, ENABLE); function.
19
20 (#) Calculate the HASH MD5 Digest using HASH_MD5() function.
21
22 (#) Calculate the HMAC MD5 Digest using HMAC_MD5() function.
23
24 @endverbatim
25 *
26 ******************************************************************************
27 * @attention
28 *
29 * <h2><center>© COPYRIGHT 2015 STMicroelectronics</center></h2>
30 *
31 * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
32 * You may not use this file except in compliance with the License.
33 * You may obtain a copy of the License at:
34 *
35 * http://www.st.com/software_license_agreement_liberty_v2
36 *
37 * Unless required by applicable law or agreed to in writing, software
38 * distributed under the License is distributed on an "AS IS" BASIS,
39 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
40 * See the License for the specific language governing permissions and
41 * limitations under the License.
42 *
43 ******************************************************************************
44 */
45
46 /* Includes ------------------------------------------------------------------*/
47 #include "stm32f4xx_hash.h"
48
49 /** @addtogroup STM32F4xx_StdPeriph_Driver
50 * @{
51 */
52
53 /** @defgroup HASH
54 * @brief HASH driver modules
55 * @{
56 */
57
58 /* Private typedef -----------------------------------------------------------*/
59 /* Private define ------------------------------------------------------------*/
60 #define MD5BUSY_TIMEOUT ((uint32_t) 0x00010000)
61
62 /* Private macro -------------------------------------------------------------*/
63 /* Private variables ---------------------------------------------------------*/
64 /* Private function prototypes -----------------------------------------------*/
65 /* Private functions ---------------------------------------------------------*/
66
67 /** @defgroup HASH_Private_Functions
68 * @{
69 */
70
71 /** @defgroup HASH_Group7 High Level MD5 functions
72 * @brief High Level MD5 Hash and HMAC functions
73 *
74 @verbatim
75 ===============================================================================
76 ##### High Level MD5 Hash and HMAC functions #####
77 ===============================================================================
78
79
80 @endverbatim
81 * @{
82 */
83
84 /**
85 * @brief Compute the HASH MD5 digest.
86 * @param Input: pointer to the Input buffer to be treated.
87 * @param Ilen: length of the Input buffer.
88 * @param Output: the returned digest
89 * @retval An ErrorStatus enumeration value:
90 * - SUCCESS: digest computation done
91 * - ERROR: digest computation failed
92 */
HASH_MD5(uint8_t * Input,uint32_t Ilen,uint8_t Output[16])93 ErrorStatus HASH_MD5(uint8_t *Input, uint32_t Ilen, uint8_t Output[16])
94 {
95 HASH_InitTypeDef MD5_HASH_InitStructure;
96 HASH_MsgDigest MD5_MessageDigest;
97 __IO uint16_t nbvalidbitsdata = 0;
98 uint32_t i = 0;
99 __IO uint32_t counter = 0;
100 uint32_t busystatus = 0;
101 ErrorStatus status = SUCCESS;
102 uint32_t inputaddr = (uint32_t)Input;
103 uint32_t outputaddr = (uint32_t)Output;
104
105
106 /* Number of valid bits in last word of the Input data */
107 nbvalidbitsdata = 8 * (Ilen % 4);
108
109 /* HASH peripheral initialization */
110 HASH_DeInit();
111
112 /* HASH Configuration */
113 MD5_HASH_InitStructure.HASH_AlgoSelection = HASH_AlgoSelection_MD5;
114 MD5_HASH_InitStructure.HASH_AlgoMode = HASH_AlgoMode_HASH;
115 MD5_HASH_InitStructure.HASH_DataType = HASH_DataType_8b;
116 HASH_Init(&MD5_HASH_InitStructure);
117
118 /* Configure the number of valid bits in last word of the data */
119 HASH_SetLastWordValidBitsNbr(nbvalidbitsdata);
120
121 /* Write the Input block in the IN FIFO */
122 for(i=0; i<Ilen; i+=4)
123 {
124 HASH_DataIn(*(uint32_t*)inputaddr);
125 inputaddr+=4;
126 }
127
128 /* Start the HASH processor */
129 HASH_StartDigest();
130
131 /* wait until the Busy flag is RESET */
132 do
133 {
134 busystatus = HASH_GetFlagStatus(HASH_FLAG_BUSY);
135 counter++;
136 }while ((counter != MD5BUSY_TIMEOUT) && (busystatus != RESET));
137
138 if (busystatus != RESET)
139 {
140 status = ERROR;
141 }
142 else
143 {
144 /* Read the message digest */
145 HASH_GetDigest(&MD5_MessageDigest);
146 *(uint32_t*)(outputaddr) = __REV(MD5_MessageDigest.Data[0]);
147 outputaddr+=4;
148 *(uint32_t*)(outputaddr) = __REV(MD5_MessageDigest.Data[1]);
149 outputaddr+=4;
150 *(uint32_t*)(outputaddr) = __REV(MD5_MessageDigest.Data[2]);
151 outputaddr+=4;
152 *(uint32_t*)(outputaddr) = __REV(MD5_MessageDigest.Data[3]);
153 }
154 return status;
155 }
156
157 /**
158 * @brief Compute the HMAC MD5 digest.
159 * @param Key: pointer to the Key used for HMAC.
160 * @param Keylen: length of the Key used for HMAC.
161 * @param Input: pointer to the Input buffer to be treated.
162 * @param Ilen: length of the Input buffer.
163 * @param Output: the returned digest
164 * @retval An ErrorStatus enumeration value:
165 * - SUCCESS: digest computation done
166 * - ERROR: digest computation failed
167 */
HMAC_MD5(uint8_t * Key,uint32_t Keylen,uint8_t * Input,uint32_t Ilen,uint8_t Output[16])168 ErrorStatus HMAC_MD5(uint8_t *Key, uint32_t Keylen, uint8_t *Input,
169 uint32_t Ilen, uint8_t Output[16])
170 {
171 HASH_InitTypeDef MD5_HASH_InitStructure;
172 HASH_MsgDigest MD5_MessageDigest;
173 __IO uint16_t nbvalidbitsdata = 0;
174 __IO uint16_t nbvalidbitskey = 0;
175 uint32_t i = 0;
176 __IO uint32_t counter = 0;
177 uint32_t busystatus = 0;
178 ErrorStatus status = SUCCESS;
179 uint32_t keyaddr = (uint32_t)Key;
180 uint32_t inputaddr = (uint32_t)Input;
181 uint32_t outputaddr = (uint32_t)Output;
182
183 /* Number of valid bits in last word of the Input data */
184 nbvalidbitsdata = 8 * (Ilen % 4);
185
186 /* Number of valid bits in last word of the Key */
187 nbvalidbitskey = 8 * (Keylen % 4);
188
189 /* HASH peripheral initialization */
190 HASH_DeInit();
191
192 /* HASH Configuration */
193 MD5_HASH_InitStructure.HASH_AlgoSelection = HASH_AlgoSelection_MD5;
194 MD5_HASH_InitStructure.HASH_AlgoMode = HASH_AlgoMode_HMAC;
195 MD5_HASH_InitStructure.HASH_DataType = HASH_DataType_8b;
196 if(Keylen > 64)
197 {
198 /* HMAC long Key */
199 MD5_HASH_InitStructure.HASH_HMACKeyType = HASH_HMACKeyType_LongKey;
200 }
201 else
202 {
203 /* HMAC short Key */
204 MD5_HASH_InitStructure.HASH_HMACKeyType = HASH_HMACKeyType_ShortKey;
205 }
206 HASH_Init(&MD5_HASH_InitStructure);
207
208 /* Configure the number of valid bits in last word of the Key */
209 HASH_SetLastWordValidBitsNbr(nbvalidbitskey);
210
211 /* Write the Key */
212 for(i=0; i<Keylen; i+=4)
213 {
214 HASH_DataIn(*(uint32_t*)keyaddr);
215 keyaddr+=4;
216 }
217
218 /* Start the HASH processor */
219 HASH_StartDigest();
220
221 /* wait until the Busy flag is RESET */
222 do
223 {
224 busystatus = HASH_GetFlagStatus(HASH_FLAG_BUSY);
225 counter++;
226 }while ((counter != MD5BUSY_TIMEOUT) && (busystatus != RESET));
227
228 if (busystatus != RESET)
229 {
230 status = ERROR;
231 }
232 else
233 {
234 /* Configure the number of valid bits in last word of the Input data */
235 HASH_SetLastWordValidBitsNbr(nbvalidbitsdata);
236
237 /* Write the Input block in the IN FIFO */
238 for(i=0; i<Ilen; i+=4)
239 {
240 HASH_DataIn(*(uint32_t*)inputaddr);
241 inputaddr+=4;
242 }
243
244 /* Start the HASH processor */
245 HASH_StartDigest();
246
247 /* wait until the Busy flag is RESET */
248 counter =0;
249 do
250 {
251 busystatus = HASH_GetFlagStatus(HASH_FLAG_BUSY);
252 counter++;
253 }while ((counter != MD5BUSY_TIMEOUT) && (busystatus != RESET));
254
255 if (busystatus != RESET)
256 {
257 status = ERROR;
258 }
259 else
260 {
261 /* Configure the number of valid bits in last word of the Key */
262 HASH_SetLastWordValidBitsNbr(nbvalidbitskey);
263
264 /* Write the Key */
265 keyaddr = (uint32_t)Key;
266 for(i=0; i<Keylen; i+=4)
267 {
268 HASH_DataIn(*(uint32_t*)keyaddr);
269 keyaddr+=4;
270 }
271
272 /* Start the HASH processor */
273 HASH_StartDigest();
274
275 /* wait until the Busy flag is RESET */
276 counter =0;
277 do
278 {
279 busystatus = HASH_GetFlagStatus(HASH_FLAG_BUSY);
280 counter++;
281 }while ((counter != MD5BUSY_TIMEOUT) && (busystatus != RESET));
282
283 if (busystatus != RESET)
284 {
285 status = ERROR;
286 }
287 else
288 {
289 /* Read the message digest */
290 HASH_GetDigest(&MD5_MessageDigest);
291 *(uint32_t*)(outputaddr) = __REV(MD5_MessageDigest.Data[0]);
292 outputaddr+=4;
293 *(uint32_t*)(outputaddr) = __REV(MD5_MessageDigest.Data[1]);
294 outputaddr+=4;
295 *(uint32_t*)(outputaddr) = __REV(MD5_MessageDigest.Data[2]);
296 outputaddr+=4;
297 *(uint32_t*)(outputaddr) = __REV(MD5_MessageDigest.Data[3]);
298 }
299 }
300 }
301 return status;
302 }
303 /**
304 * @}
305 */
306
307 /**
308 * @}
309 */
310
311 /**
312 * @}
313 */
314
315 /**
316 * @}
317 */
318
319 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
320
321