1 /*!
2  * @file        apm32f4xx_hash.c
3  *
4  * @brief       This file provides all the HASH firmware functions
5  *
6  * @version     V1.0.2
7  *
8  * @date        2022-06-23
9  *
10  * @attention
11  *
12  *  Copyright (C) 2021-2022 Geehy Semiconductor
13  *
14  *  You may not use this file except in compliance with the
15  *  GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
16  *
17  *  The program is only for reference, which is distributed in the hope
18  *  that it will be usefull and instructional for customers to develop
19  *  their software. Unless required by applicable law or agreed to in
20  *  writing, the program is distributed on an "AS IS" BASIS, WITHOUT
21  *  ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
22  *  See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
23  *  and limitations under the License.
24  */
25 
26 #include "apm32f4xx_hash.h"
27 #include "apm32f4xx_rcm.h"
28 
29 /** @addtogroup APM32F4xx_StdPeriphDriver
30   @{
31 */
32 
33 /** @defgroup HASH_Driver
34   * @brief HASH driver modules
35   @{
36 */
37 
38 /** @defgroup HASH_Functions
39   @{
40 */
41 
42 /*!
43  * @brief     Reset the HASH peripheral register.
44  *
45  * @param     None
46  *
47  * @retval    None
48  */
HASH_Reset(void)49 void HASH_Reset(void)
50 {
51     RCM_EnableAHB2PeriphReset(RCM_AHB2_PERIPH_HASH);
52     RCM_DisableAHB2PeriphReset(RCM_AHB2_PERIPH_HASH);
53 }
54 
55 /*!
56  * @brief     Config the HASH peripheral according to the specified parameters in the hashConfig.
57  *
58  * @param     hashConfig: pointer to a HASH_Config_T structure.
59  *
60  * @retval    None
61  */
HASH_Config(HASH_Config_T * hashConfig)62 void HASH_Config(HASH_Config_T *hashConfig)
63 {
64     /* Configure the Algorithm used, algorithm mode and the datatype */
65     HASH->CTRL_B.ALGSEL = RESET;
66     HASH->CTRL_B.DTYPE = RESET;
67     HASH->CTRL_B.MODESEL = RESET;
68 
69     HASH->CTRL_B.ALGSEL = hashConfig->algoSelect;
70     HASH->CTRL_B.DTYPE = hashConfig->dataType;
71     HASH->CTRL_B.MODESEL = hashConfig->algoMode;
72 
73     /* if algorithm mode is HMAC, set the Key */
74     if (hashConfig->algoMode == HASH_ALGO_MODE_HMAC)
75     {
76         HASH->CTRL_B.LKEYSEL = RESET;
77         HASH->CTRL_B.LKEYSEL = hashConfig->hmacKeyType;
78     }
79 
80     /* Reset the HASH processor core, so that the HASH will be ready to compute
81      the message digest of a new message */
82     HASH->CTRL_B.INITCAL = SET;
83 }
84 
85 /*!
86  * @brief     Fills each HASH_Config_T member with its default value.
87  *
88  * @param     hashConfig: pointer to an HASH_Config_T structure.
89  *
90  * @retval    None
91  */
HASH_ConfigStructInit(HASH_Config_T * hashConfig)92 void HASH_ConfigStructInit(HASH_Config_T *hashConfig)
93 {
94     hashConfig->algoSelect = HASH_ALGO_SELECTION_SHA1;
95     hashConfig->algoMode = HASH_ALGO_MODE_HASH;
96     hashConfig->dataType = HASH_DATA_TYPE_32B;
97     hashConfig->hmacKeyType = HASH_HMAC_KEY_TYPE_SHORTKEY;
98 }
99 
100 /*!
101  * @brief     Resets the HASH processor core.
102  *
103  * @param     None
104  *
105  * @retval    None
106  */
HASH_ResetProceCore(void)107 void HASH_ResetProceCore(void)
108 {
109     HASH->CTRL_B.INITCAL = SET;
110 }
111 
112 /*!
113  * @brief     Configure the Number of valid bits in last word of the message.
114  *
115  * @param     ValidNumber: Number of valid bits in last word of the message.
116  *
117  * @retval    None
118  */
HASH_ConfigLastWordValidBitsNbr(uint16_t validNumber)119 void HASH_ConfigLastWordValidBitsNbr(uint16_t validNumber)
120 {
121     HASH->START_B.LWNUM = RESET;
122     HASH->START_B.LWNUM = validNumber;
123 }
124 
125 /*!
126  * @brief     Writes data in the Input Data FIFO.
127  *
128  * @param     data: new data of the message to be processed.
129  *
130  * @retval    None
131  */
HASH_WritesInputData(uint32_t data)132 void HASH_WritesInputData(uint32_t data)
133 {
134     HASH->INDATA_B.INDATA = data;
135 }
136 
137 /*!
138  * @brief     Read the number of words already pushed into the IN FIFO.
139  *
140  * @param     None
141  *
142  * @retval    None
143  */
HASH_ReadInFIFOWordsNbr(void)144 uint8_t HASH_ReadInFIFOWordsNbr(void)
145 {
146     return (HASH->CTRL_B.WNUM);
147 }
148 
149 /*!
150  * @brief     Read the provides message digest.
151  *
152  * @param     messageDigest: pointer to a HASH_Config_T structure.
153  *
154  * @retval    None
155  */
HASH_ReadDigest(HASH_MessageDigest_T * messageDigest)156 void HASH_ReadDigest(HASH_MessageDigest_T *messageDigest)
157 {
158     /* Read the data field */
159     messageDigest->Data[0] = HASH->DIG[0];
160     messageDigest->Data[1] = HASH->DIG[1];
161     messageDigest->Data[2] = HASH->DIG[2];
162     messageDigest->Data[3] = HASH->DIG[3];
163     messageDigest->Data[4] = HASH->DIG[4];
164 }
165 
166 /*!
167  * @brief     Start the Digest calculation.
168  *
169  * @param     None
170  *
171  * @retval    None
172  */
HASH_StartDigest(void)173 void HASH_StartDigest(void)
174 {
175     HASH->START_B.DIGCAL = SET;
176 }
177 
178 /*!
179  * @brief     Read the Hash peripheral Context.
180  *
181  * @param     contextRead: pointer to a HASH_Context_T structure that contains
182  *            the repository for current context.
183  *
184  * @retval    None
185  */
HASH_ReadContext(HASH_Context_T * contextRead)186 void HASH_ReadContext(HASH_Context_T *contextRead)
187 {
188     uint8_t i = 0;
189 
190     contextRead->HASH_INT = HASH->INT;
191     contextRead->HASH_START = HASH->START;
192     contextRead->HASH_CTRL  = HASH->CTRL;
193 
194     for (i = 0; i <= 50; i++)
195     {
196         contextRead->HASH_CTSWAP[i] = HASH->CTSWAP[i];
197     }
198 }
199 
200 /*!
201  * @brief     Write the Hash peripheral Context.
202  *
203  * @param     contextWrite: pointer to a HASH_Context_T structure that contains
204  *            the repository for current context.
205  *
206  * @retval    None
207  */
HASH_WriteContext(HASH_Context_T * contextWrite)208 void HASH_WriteContext(HASH_Context_T *contextWrite)
209 {
210     uint8_t i = 0;
211 
212     HASH->INT = contextWrite->HASH_INT;
213     HASH->START = contextWrite->HASH_START;
214     HASH->CTRL = contextWrite->HASH_CTRL;
215 
216     HASH->CTRL_B.INITCAL = SET;
217 
218     for (i = 0; i <= 50; i++)
219     {
220         HASH->CTSWAP[i] = contextWrite->HASH_CTSWAP[i];
221     }
222 }
223 
224 /*!
225  * @brief     Enables the HASH DMA interface.
226  *
227  * @param     None
228  *
229  * @retval    None
230  */
HASH_EnableDMA(void)231 void HASH_EnableDMA(void)
232 {
233     HASH->CTRL_B.DMAEN = SET;
234 }
235 
236 /*!
237  * @brief     Disabled the HASH DMA interface.
238  *
239  * @param     None
240  *
241  * @retval    None
242  */
HASH_DisableDMA(void)243 void HASH_DisableDMA(void)
244 {
245     HASH->CTRL_B.DMAEN = RESET;
246 }
247 
248 /*!
249  * @brief     Enables the specified HASH interrupts.
250  *
251  * @param     interrupt: Select the ADC interrupt sources
252  *                       This parameter can be any combination of the following values:
253  *                       @arg HASH_INT_INDATAINT: Input Data interrupt mask
254  *                       @arg HASH_INT_DCALCINT: Digest calculation completion Data interrupt mask
255  *
256  * @retval    None
257  */
HASH_EnableInterrupt(uint32_t interrupt)258 void HASH_EnableInterrupt(uint32_t interrupt)
259 {
260     HASH->INT |= interrupt;
261 }
262 
263 /*!
264  * @brief     Disables the specified HASH interrupts.
265  *
266  * @param     interrupt: Select the ADC interrupt sources
267  *                       This parameter can be any combination of the following values:
268  *                       @arg HASH_INT_INDATAINT: Input Data interrupt mask
269  *                       @arg HASH_INT_DCALCINT: Digest calculation completion Data interrupt mask
270  *
271  * @retval    None
272  */
HASH_DisableInterrupt(uint32_t interrupt)273 void HASH_DisableInterrupt(uint32_t interrupt)
274 {
275     HASH->INT &= (uint32_t)~interrupt;
276 }
277 
278 /*!
279  * @brief     Reads the pending HASH flag
280  *
281  * @param     flag: Select the flag to check
282  *                  This parameter can be one of the following values:
283  *             @arg HASH_FLAG_INDATAINT: Data input interrupt status flag
284  *             @arg HASH_FLAG_DCALCINT: Digest calculation completion interrupt status flag
285  *             @arg HASH_FLAG_DMA: DMAS Status flag
286  *             @arg HASH_FLAG_BUSY: Busy flag
287  *             @arg HASH_FLAG_DINNEMPT: Data Input register (DIN) not empty status flag
288  *
289  * @retval    SET or RESET
290  */
HASH_ReadFlagStatus(HASH_FLAG_T flag)291 uint8_t HASH_ReadFlagStatus(HASH_FLAG_T flag)
292 {
293     uint32_t reg = 0;
294 
295     if (flag == HASH_FLAG_DINNEMPT)
296     {
297         reg = HASH->CTRL;
298     }
299     else
300     {
301         reg = HASH->STS;
302     }
303 
304     return (reg & flag) ? SET : RESET;
305 }
306 
307 /*!
308  * @brief     Clears the pending HASH flag
309  *
310  * @param     flag: Select the flag to check
311  *                  This parameter can be one of the following values:
312  *             @arg HASH_FLAG_INDATAINT: Data input interrupt status flag
313  *             @arg HASH_FLAG_DCALCINT: Digest calculation completion interrupt status flag
314  *
315  * @retval    None
316  */
HASH_ClearStatusFlag(HASH_FLAG_T flag)317 void HASH_ClearStatusFlag(HASH_FLAG_T flag)
318 {
319     if (flag == HASH_FLAG_INDATAINT)
320     {
321         HASH->STS_B.INDATAINT = BIT_RESET;
322     }
323     else if (flag == HASH_FLAG_DCALCINT)
324     {
325         HASH->STS_B.DCALCINT = BIT_RESET;
326     }
327 }
328 
329 /*!
330  * @brief     Reads the specified HASH Interrupt flag.
331  *
332  * @param     flag: Select the ADC interrupt source.
333  *                  This parameter can be one of the following values:
334  *             @arg HASH_INT_FLAG_INDATA: Input Data interrupt
335  *             @arg HASH_INT_FLAG_DCALC: Digest Calculation Completion Interrupt
336  *
337  * @retval    SET or RESET
338  */
HASH_ReadIntFlag(HASH_INT_FLAG_T flag)339 uint8_t HASH_ReadIntFlag(HASH_INT_FLAG_T flag)
340 {
341     uint32_t intStatus = 0, reg = 0;
342 
343     intStatus = HASH->INT;
344     reg = HASH->STS;
345 
346     return (intStatus & (reg & flag)) ? SET : RESET;
347 }
348 
349 /*!
350  * @brief     Clears the pending HASH flag
351  *
352  * @param     flag: Select the flag to check
353  *                  This parameter can be one of the following values:
354  *             @arg HASH_INT_FLAG_INDATA: Input Data interrupt
355  *             @arg HASH_INT_FLAG_DCALC: Digest Calculation Completion Interrupt
356  *
357  * @retval    None
358  */
HASH_ClearIntFlag(HASH_INT_FLAG_T flag)359 void HASH_ClearIntFlag(HASH_INT_FLAG_T flag)
360 {
361     if (flag == HASH_INT_FLAG_INDATA)
362     {
363         HASH->STS_B.INDATAINT = BIT_RESET;
364     }
365     else if (flag == HASH_INT_FLAG_DCALC)
366     {
367         HASH->STS_B.DCALCINT = BIT_RESET;
368     }
369 }
370 
371 /*!
372  * @brief     Waits for Compute data
373  *
374  * @param      timeOut: Waits for Compute time
375  *
376  * @retval    0: No block is currently being compute
377  *            1: The hash core is compute a block of data
378  *
379  */
HASH_WaitForCompute(uint32_t timeOut)380 uint8_t HASH_WaitForCompute(uint32_t timeOut)
381 {
382     __IO uint8_t flag = SET;
383     uint32_t time = timeOut;
384 
385     while ((flag == SET) && (time > 0))
386     {
387         flag = HASH_ReadFlagStatus(HASH_FLAG_BUSY);
388         time --;
389     }
390 
391     if ((flag == RESET) && (time > 0))
392     {
393         return 0;
394     }
395 
396     return 1;
397 }
398 
399 /**@} end of group HASH_Functions */
400 /**@} end of group HASH_Driver */
401 /**@} end of group APM32F4xx_StdPeriphDriver */
402