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