1 /*!
2 * @file apm32f4xx_hash_sha1.c
3 *
4 * @brief This file provides high level functions to compute the HASH SHA1 and
5 * HMAC SHA1 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 #include "apm32f4xx_hash.h"
28
29 /** @addtogroup APM32F4xx_StdPeriphDriver
30 @{
31 */
32
33 /** @defgroup HASH_SHA1_Driver
34 * @brief HASH SHA1 driver modules
35 @{
36 */
37
38 /** @defgroup HASH_SHA1_Functions
39 @{
40 */
41
42 /** @defgroup HASH_SHA1_Macros Macros
43 @{
44 */
45
46 /* HASH SHA1 timeout definition */
47 #define SHA1_BUSY_TIMEOUT ((uint32_t) 0x00010000)
48
49 /**@} end of group HASH_SHA1_Macros */
50
51 /*!
52 * @brief Compute the HASH SHA1 digest
53 *
54 * @param inBuffer: pointer to the input buffer to be treated
55 *
56 * @param lenBuffer: length of the input buffer.
57 *
58 * @param outBuffer: the returned digest.
59 *
60 * @retval An ErrorStatus enumeration value:
61 * SUCCESS: digest computation done
62 * ERROR: digest computation failed
63 *
64 */
HASH_ComputeSHA1(uint8_t * inBuffer,uint32_t lenBuffer,uint8_t outBuffer[20])65 uint8_t HASH_ComputeSHA1(uint8_t *inBuffer, uint32_t lenBuffer,
66 uint8_t outBuffer[20])
67 {
68 HASH_Config_T hashSHA1Config;
69 HASH_MessageDigest_T hashSHA1MessageDigest;
70 uint16_t nBufferBits = 0;
71 uint32_t m = 0;
72 uint32_t inBufferaddr = (uint32_t)inBuffer;
73 uint32_t outBufferaddr = (uint32_t)outBuffer;
74
75 nBufferBits = (lenBuffer % 4) * 8;
76
77 HASH_Reset();
78
79 /* Configure the number of valid bits in last word of the data */
80 hashSHA1Config.algoSelect = HASH_ALGO_SELECTION_SHA1;
81 hashSHA1Config.algoMode = HASH_ALGO_MODE_HASH;
82 hashSHA1Config.dataType = HASH_DATA_TYPE_8B;
83 HASH_Config(&hashSHA1Config);
84 HASH_ConfigLastWordValidBitsNbr(nBufferBits);
85
86 /* Write the input block in the IN FIFO */
87 for (m = 0; m < lenBuffer; m += 4)
88 {
89 HASH_WritesInputData(*(uint32_t *)inBufferaddr);
90 inBufferaddr += 4;
91 }
92
93 /* Start the HASH processor */
94 HASH_StartDigest();
95
96 /* wait until the Busy flag is RESET */
97 if (HASH_WaitForCompute(SHA1_BUSY_TIMEOUT) != 0)
98 {
99 return ERROR;
100 }
101 else
102 {
103 /* Read the message digest */
104 HASH_ReadDigest(&hashSHA1MessageDigest);
105
106 *(uint32_t *)(outBufferaddr) = __REV(hashSHA1MessageDigest.Data[0]);
107
108 outBufferaddr += 4;
109 *(uint32_t *)(outBufferaddr) = __REV(hashSHA1MessageDigest.Data[1]);
110
111 outBufferaddr += 4;
112 *(uint32_t *)(outBufferaddr) = __REV(hashSHA1MessageDigest.Data[2]);
113
114 outBufferaddr += 4;
115 *(uint32_t *)(outBufferaddr) = __REV(hashSHA1MessageDigest.Data[3]);
116
117 outBufferaddr += 4;
118 *(uint32_t *)(outBufferaddr) = __REV(hashSHA1MessageDigest.Data[4]);
119 }
120
121 return SUCCESS;
122 }
123
124 /*!
125 * @brief Compute the HMAC SHA1 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_ComputeSHA1(uint8_t * key,uint32_t lenkey,uint8_t * inBuffer,uint32_t lenBuffer,uint8_t outBuffer[20])142 uint8_t HMAC_ComputeSHA1(uint8_t *key, uint32_t lenkey, uint8_t *inBuffer,
143 uint32_t lenBuffer, uint8_t outBuffer[20])
144 {
145 HASH_Config_T hmacSHA1Config;
146 HASH_MessageDigest_T hashSHA1MessageDigest;
147 uint16_t nBufferBits = 0;
148 uint16_t nuValidKey = 0;
149 uint32_t m = 0;
150 uint32_t keyaddr = (uint32_t)key;
151 uint32_t inputaddr = (uint32_t)inBuffer;
152 uint32_t outputaddr = (uint32_t)outBuffer;
153
154 nBufferBits = 8 * (lenBuffer % 4);
155 nuValidKey = 8 * (lenkey % 4);
156
157 HASH_Reset();
158
159 /* HASH Configuration */
160 hmacSHA1Config.algoSelect = HASH_ALGO_SELECTION_SHA1;
161 hmacSHA1Config.algoMode = HASH_ALGO_MODE_HMAC;
162 hmacSHA1Config.dataType = HASH_DATA_TYPE_8B;
163
164 if (lenkey > 64)
165 {
166 hmacSHA1Config.hmacKeyType = HASH_HMAC_KEY_TYPE_LONGKEY;
167 }
168 else
169 {
170 hmacSHA1Config.hmacKeyType = HASH_HMAC_KEY_TYPE_SHORTKEY;
171 }
172
173 HASH_Config(&hmacSHA1Config);
174 HASH_ConfigLastWordValidBitsNbr(nuValidKey);
175
176 /* Write the key */
177 for (m = 0; m < lenkey; m += 4)
178 {
179 HASH_WritesInputData(*(uint32_t *)keyaddr);
180 keyaddr += 4;
181 }
182
183 HASH_StartDigest();
184
185 /* wait until the Busy flag is RESET */
186 if (HASH_WaitForCompute(SHA1_BUSY_TIMEOUT) != 0)
187 {
188 return ERROR;
189 }
190 else
191 {
192 HASH_ConfigLastWordValidBitsNbr(nBufferBits);
193
194 for (m = 0; m < lenkey; m += 4)
195 {
196 HASH_WritesInputData(*(uint32_t *)inputaddr);
197 inputaddr += 4;
198 }
199
200 HASH_StartDigest();
201
202 /* wait until the Busy flag is RESET */
203 if (HASH_WaitForCompute(SHA1_BUSY_TIMEOUT) != 0)
204 {
205 return ERROR;
206 }
207 else
208 {
209 HASH_ConfigLastWordValidBitsNbr(nuValidKey);
210 /* Write the key */
211 keyaddr = (uint32_t)key;
212
213 for (m = 0; m < lenkey; m += 4)
214 {
215 HASH_WritesInputData(*(uint32_t *)keyaddr);
216 keyaddr += 4;
217 }
218
219 /* Start the HASH processor */
220 HASH_StartDigest();
221
222 /* wait until the Busy flag is RESET */
223 if (HASH_WaitForCompute(SHA1_BUSY_TIMEOUT) != 0)
224 {
225 return ERROR;
226 }
227 else
228 {
229 /* Read the message digest */
230 HASH_ReadDigest(&hashSHA1MessageDigest);
231 *(uint32_t *)(outputaddr) = __REV(hashSHA1MessageDigest.Data[0]);
232
233 outputaddr += 4;
234 *(uint32_t *)(outputaddr) = __REV(hashSHA1MessageDigest.Data[1]);
235
236 outputaddr += 4;
237 *(uint32_t *)(outputaddr) = __REV(hashSHA1MessageDigest.Data[2]);
238
239 outputaddr += 4;
240 *(uint32_t *)(outputaddr) = __REV(hashSHA1MessageDigest.Data[3]);
241
242 outputaddr += 4;
243 *(uint32_t *)(outputaddr) = __REV(hashSHA1MessageDigest.Data[4]);
244 }
245 }
246 }
247
248 return SUCCESS;
249 }
250
251 /**@} end of group HASH_SHA1_Functions */
252 /**@} end of group HASH_SHA1_Driver */
253 /**@} end of group APM32F4xx_StdPeriphDriver */
254