1 /*!
2 * @file apm32f4xx_hash_md5.c
3 *
4 * @brief This file provides high level functions to compute the HASH MD5 and
5 * HMAC MD5 Digest of an input message.
6 *
7 * @version V1.0.2
8 *
9 * @date 2022-06-23
10 *
11 * @attention
12 *
13 * Copyright (C) 2021-2022 Geehy Semiconductor
14 *
15 * You may not use this file except in compliance with the
16 * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
17 *
18 * The program is only for reference, which is distributed in the hope
19 * that it will be usefull and instructional for customers to develop
20 * their software. Unless required by applicable law or agreed to in
21 * writing, the program is distributed on an "AS IS" BASIS, WITHOUT
22 * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
23 * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
24 * and limitations under the License.
25 */
26
27
28 #include "apm32f4xx_hash.h"
29
30 /** @addtogroup APM32F4xx_StdPeriphDriver
31 @{
32 */
33
34 /** @defgroup HASH_MD5_Driver
35 * @brief HASH MD5 driver modules
36 @{
37 */
38
39 /** @defgroup HASH_MD5_Functions
40 @{
41 */
42
43 /** @defgroup HASH_MD5_Macros Macros
44 @{
45 */
46
47 /* HASH MD5 timeout definition */
48 #define MD5_BUSY_TIMEOUT ((uint32_t) 0x00010000)
49
50 /**@} end of group HASH_MD5_Macros*/
51
52 /*!
53 * @brief Compute the HASH MD5 digest
54 *
55 * @param inBuffer: pointer to the input buffer to be treated
56 *
57 * @param lenBuffer: length of the input buffer.
58 *
59 * @param outBuffer: the returned digest.
60 *
61 * @retval An ErrorStatus enumeration value:
62 * SUCCESS: digest computation done
63 * ERROR: digest computation failed
64 *
65 */
HASH_ComputeMD5(uint8_t * inBuffer,uint32_t lenBuffer,uint8_t outBuffer[16])66 uint8_t HASH_ComputeMD5(uint8_t *inBuffer, uint32_t lenBuffer,
67 uint8_t outBuffer[16])
68 {
69 HASH_Config_T hashMD5Config;
70 HASH_MessageDigest_T hashMD5MessageDigest;
71 uint16_t nuValidBits = 0;
72 uint32_t m = 0;
73 uint32_t inBufferaddr = (uint32_t)inBuffer;
74 uint32_t outBufferaddr = (uint32_t)outBuffer;
75
76 nuValidBits = 8 * (lenBuffer % 4);
77
78 HASH_Reset();
79
80 /* HASH Configuration */
81 hashMD5Config.algoSelect = HASH_ALGO_SELECTION_MD5;
82 hashMD5Config.algoMode = HASH_ALGO_MODE_HASH;
83 hashMD5Config.dataType = HASH_DATA_TYPE_8B;
84 HASH_Config(&hashMD5Config);
85
86 /* Configure the number of valid bits in last word of the data */
87 HASH_ConfigLastWordValidBitsNbr(nuValidBits);
88
89 /* Write the input block in the IN FIFO */
90 for (m = 0; m < lenBuffer; m += 4)
91 {
92 HASH_WritesInputData(*(uint32_t *)inBufferaddr);
93 inBufferaddr += 4;
94 }
95
96 /* Start the HASH processor */
97 HASH_StartDigest();
98
99 /* wait until the Busy flag is RESET */
100 if (HASH_WaitForCompute(MD5_BUSY_TIMEOUT) != 0)
101 {
102 return ERROR;
103 }
104 else
105 {
106 /* Read the message digest */
107 HASH_ReadDigest(&hashMD5MessageDigest);
108
109 *(uint32_t *)(outBufferaddr) = __REV(hashMD5MessageDigest.Data[0]);
110
111 outBufferaddr += 4;
112 *(uint32_t *)(outBufferaddr) = __REV(hashMD5MessageDigest.Data[1]);
113
114 outBufferaddr += 4;
115 *(uint32_t *)(outBufferaddr) = __REV(hashMD5MessageDigest.Data[2]);
116
117 outBufferaddr += 4;
118 *(uint32_t *)(outBufferaddr) = __REV(hashMD5MessageDigest.Data[3]);
119 }
120
121 return SUCCESS;
122 }
123
124 /*!
125 * @brief Compute the HMAC MD5 digest
126 *
127 * @param key: pointer to the Key used for HMAC
128 *
129 * @param lenkey: length of the Key used for HMAC
130 *
131 * @param inBuffer: pointer to the Input buffer to be treated
132 *
133 * @param lenBuffer: length of the Input buffer
134 *
135 * @param outBuffer: the returned digest
136 *
137 * @retval An ErrorStatus enumeration value:
138 * SUCCESS: digest computation done
139 * ERROR: digest computation failed
140 *
141 */
HMAC_ComputeMD5(uint8_t * key,uint32_t keylen,uint8_t * inBuffer,uint32_t lenBuffer,uint8_t outBuffer[16])142 uint8_t HMAC_ComputeMD5(uint8_t *key, uint32_t keylen, uint8_t *inBuffer,
143 uint32_t lenBuffer, uint8_t outBuffer[16])
144 {
145 HASH_Config_T hmacMD5Config;
146 HASH_MessageDigest_T hmacMD5MessageDigest;
147 uint16_t nuValidBits = 0;
148 uint16_t nuValidKey = 0;
149 uint32_t m = 0;
150 uint32_t keyaddr = (uint32_t)key;
151 uint32_t inBufferaddr = (uint32_t)inBuffer;
152 uint32_t outBufferaddr = (uint32_t)outBuffer;
153
154 nuValidBits = 8 * (lenBuffer % 4);
155 nuValidKey = 8 * (keylen % 4);
156
157 HASH_Reset();
158
159 /* HASH Configuration */
160 hmacMD5Config.algoSelect = HASH_ALGO_SELECTION_MD5;
161 hmacMD5Config.algoMode = HASH_ALGO_MODE_HMAC;
162 hmacMD5Config.dataType = HASH_DATA_TYPE_8B;
163
164 if (keylen > 64)
165 {
166 hmacMD5Config.hmacKeyType = HASH_HMAC_KEY_TYPE_LONGKEY;
167 }
168 else
169 {
170 hmacMD5Config.hmacKeyType = HASH_HMAC_KEY_TYPE_SHORTKEY;
171 }
172
173 HASH_Config(&hmacMD5Config);
174 HASH_ConfigLastWordValidBitsNbr(nuValidKey);
175
176 for (m = 0; m < keylen; m += 4)
177 {
178 HASH_WritesInputData(*(uint32_t *)keyaddr);
179 keyaddr += 4;
180 }
181
182 /* Start the HASH processor */
183 HASH_StartDigest();
184
185 /* wait until the Busy flag is RESET */
186 if (HASH_WaitForCompute(MD5_BUSY_TIMEOUT) != 0)
187 {
188 return ERROR;
189 }
190 else
191 {
192 /* Configure the number of valid bits in last word of the input data */
193 HASH_ConfigLastWordValidBitsNbr(nuValidBits);
194
195 /* Write the input block in the IN FIFO */
196 for (m = 0; m < lenBuffer; m += 4)
197 {
198 HASH_WritesInputData(*(uint32_t *)inBufferaddr);
199 inBufferaddr += 4;
200 }
201
202 /* Start the HASH processor */
203 HASH_StartDigest();
204
205 /* wait until the Busy flag is RESET */
206 if (HASH_WaitForCompute(MD5_BUSY_TIMEOUT) != 0)
207 {
208 return ERROR;
209 }
210 else
211 {
212 HASH_ConfigLastWordValidBitsNbr(nuValidKey);
213 keyaddr = (uint32_t)key;
214
215 for (m = 0; m < keylen; m += 4)
216 {
217 HASH_WritesInputData(*(uint32_t *)keyaddr);
218 keyaddr += 4;
219 }
220
221 /* Start the HASH processor */
222 HASH_StartDigest();
223
224 /* wait until the Busy flag is RESET */
225 if (HASH_WaitForCompute(MD5_BUSY_TIMEOUT) != 0)
226 {
227 return ERROR;
228 }
229 else
230 {
231 /* Read the message digest */
232 HASH_ReadDigest(&hmacMD5MessageDigest);
233
234 *(uint32_t *)(outBufferaddr) = __REV(hmacMD5MessageDigest.Data[0]);
235
236 outBufferaddr += 4;
237 *(uint32_t *)(outBufferaddr) = __REV(hmacMD5MessageDigest.Data[1]);
238
239 outBufferaddr += 4;
240 *(uint32_t *)(outBufferaddr) = __REV(hmacMD5MessageDigest.Data[2]);
241
242 outBufferaddr += 4;
243 *(uint32_t *)(outBufferaddr) = __REV(hmacMD5MessageDigest.Data[3]);
244 }
245 }
246 }
247
248 return SUCCESS;
249 }
250
251 /**@} end of group HASH_MD5_Functions */
252 /**@} end of group HASH_MD5_Driver */
253 /**@} end of group APM32F4xx_StdPeriphDriver */
254