summaryrefslogtreecommitdiff
path: root/bsp/hc32f4a0/Libraries/HC32F4A0_StdPeriph_Driver/src/hc32f4a0_hash.c
blob: 102ab0ab33d3ad59d6f363b1ec767f27627f2315 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
/**
 *******************************************************************************
 * @file  hc32f4a0_hash.c
 * @brief This file provides firmware functions to manage the HASH
 @verbatim
   Change Logs:
   Date             Author          Notes
   2020-06-12       Heqb          First version
 @endverbatim
 *******************************************************************************
 * Copyright (C) 2020, Huada Semiconductor Co., Ltd. All rights reserved.
 *
 * This software component is licensed by HDSC under BSD 3-Clause license
 * (the "License"); You may not use this file except in compliance with the
 * License. You may obtain a copy of the License at:
 *                    opensource.org/licenses/BSD-3-Clause
 *
 *******************************************************************************
 */

/*******************************************************************************
 * Include files
 ******************************************************************************/
#include "hc32f4a0_hash.h"
#include "hc32f4a0_utility.h"

/**
 * @addtogroup HC32F4A0_DDL_Driver
 * @{
 */

/**
 * @defgroup DDL_HASH HASH
 * @brief HASH Driver Library
 * @{
 */

#if (DDL_HASH_ENABLE == DDL_ON)

/*******************************************************************************
 * Local type definitions ('typedef')
 ******************************************************************************/

/*******************************************************************************
 * Local pre-processor symbols/macros ('#define')
 ******************************************************************************/
/**
 * @defgroup HASH_Local_Macros HASH Local Macros
 * @{
 */
#define HASH_TIMEOUT                  (6000U)

#define HASH_INT_MASK                 (HASH_INT_GROUP | HASH_INT_ALL)

#define HASH_FLAG_MASK                (HASH_FLAG_START | HASH_FLAG_BUSY | \
                                       HASH_FLAG_CYC_END | HASH_FLAG_HMAC_END)

#define HASH_CLR_FLAG_MASK            (HASH_FLAG_CYC_END | HASH_FLAG_HMAC_END)
/**
 * @defgroup HASH_Check_Parameters_Validity HASH Check Parameters Validity
 * @{
 */
#define IS_VALID_MODE(x)                                                       \
(   ((x) == HASH_MODE_SHA_256)                              ||                 \
    ((x) == HASH_MODE_HMAC))

#define IS_VALID_KEY_LEN(x)                                                    \
(   ((x) == HASH_KEY_LEN_LONG)                              ||                 \
    ((x) == HASH_KEY_LEN_SHORT))

#define IS_VALID_INT_CMD(x)               (((x) | HASH_INT_MASK) == HASH_INT_MASK)

#define IS_VALID_FLAG(x)                  (((x) | HASH_FLAG_MASK) == HASH_FLAG_MASK)

#define IS_VALID_MSG_GRP(x)                                                    \
(   ((x) == HASH_MSG_GRP_FIRST)                             ||                 \
    ((x) == HASH_MSG_GRP_END)                               ||                 \
    ((x) == HASH_MSG_GRP_ONLY_ONE))

#define IS_VALID_FLAG_CLR(x)                                                   \
(   ((x) != 0x0UL)                                          &&                 \
    (((x) | HASH_CLR_FLAG_MASK) == HASH_CLR_FLAG_MASK))

#define IS_VALID_COM_TRIG(x)                                                   \
(   ((x) != 0x0UL)                                          &&                 \
    (((x) | HASH_COM_TRIG_MASk) == HASH_COM_TRIG_MASk))

#define IS_VALID_TRG_REG_SEL(x)                                                \
(   ((x) == HASH_TRIG_REG_BLKCOM)                           ||                 \
    ((x) == HASH_TRIG_REG_TRNCOM))

#define IS_VALID_TRG_SRC_SEL(x)                                                \
(   ((x) == HASH_TRG_SRC_DMA1_BTC0)                         ||                 \
    ((x) == HASH_TRG_SRC_DMA1_BTC1)                         ||                 \
    ((x) == HASH_TRG_SRC_DMA1_BTC2)                         ||                 \
    ((x) == HASH_TRG_SRC_DMA1_BTC3)                         ||                 \
    ((x) == HASH_TRG_SRC_DMA1_BTC4)                         ||                 \
    ((x) == HASH_TRG_SRC_DMA1_BTC5)                         ||                 \
    ((x) == HASH_TRG_SRC_DMA1_BTC6)                         ||                 \
    ((x) == HASH_TRG_SRC_DMA1_BTC7)                         ||                 \
    ((x) == HASH_TRG_SRC_DMA1_TC0)                          ||                 \
    ((x) == HASH_TRG_SRC_DMA1_TC1)                          ||                 \
    ((x) == HASH_TRG_SRC_DMA1_TC2)                          ||                 \
    ((x) == HASH_TRG_SRC_DMA1_TC3)                          ||                 \
    ((x) == HASH_TRG_SRC_DMA1_TC4)                          ||                 \
    ((x) == HASH_TRG_SRC_DMA1_TC5)                          ||                 \
    ((x) == HASH_TRG_SRC_DMA1_TC6)                          ||                 \
    ((x) == HASH_TRG_SRC_DMA1_TC7)                          ||                 \
    ((x) == HASH_TRG_SRC_DMA2_BTC0)                         ||                 \
    ((x) == HASH_TRG_SRC_DMA2_BTC1)                         ||                 \
    ((x) == HASH_TRG_SRC_DMA2_BTC2)                         ||                 \
    ((x) == HASH_TRG_SRC_DMA2_BTC3)                         ||                 \
    ((x) == HASH_TRG_SRC_DMA2_BTC4)                         ||                 \
    ((x) == HASH_TRG_SRC_DMA2_BTC5)                         ||                 \
    ((x) == HASH_TRG_SRC_DMA2_BTC6)                         ||                 \
    ((x) == HASH_TRG_SRC_DMA2_BTC7)                         ||                 \
    ((x) == HASH_TRG_SRC_DMA2_TC0)                          ||                 \
    ((x) == HASH_TRG_SRC_DMA2_TC1)                          ||                 \
    ((x) == HASH_TRG_SRC_DMA2_TC2)                          ||                 \
    ((x) == HASH_TRG_SRC_DMA2_TC3)                          ||                 \
    ((x) == HASH_TRG_SRC_DMA2_TC4)                          ||                 \
    ((x) == HASH_TRG_SRC_DMA2_TC5)                          ||                 \
    ((x) == HASH_TRG_SRC_DMA2_TC6)                          ||                 \
    ((x) == HASH_TRG_SRC_DMA2_TC7))
/**
 * @}
 */

/**
 * @}
 */

/*******************************************************************************
 * Global variable definitions (declared in header file with 'extern')
 ******************************************************************************/

/*******************************************************************************
 * Local function prototypes ('static')
 ******************************************************************************/
static void HASH_WriteData(uint8_t u8Data[]);
static en_result_t HASH_Fill_Calc_Data(const uint8_t au8Data[], uint32_t u32DataSize);

/*******************************************************************************
 * Local variable definitions ('static')
 ******************************************************************************/

/*******************************************************************************
 * Function implementation - global ('extern') and local ('static')
 ******************************************************************************/
/**
 * @defgroup HASH_Global_Functions HASH Global Functions
 * @{
 */

/**
 * @brief  HASH calculate.
 * @param  [in] pvSrcData           Pointer to the source data buffer
 * @param  [in] u32SrcDataSize      Length of the input buffer in bytes
 * @param  [out] au8MsgDigest       Buffer of the digest. The size must be 32 bytes
 * @retval Ok: Success
 *         ErrorBufferFull: Filling Error
 *         ErrorInvalidParameter: Parameter error
 */
en_result_t HASH_Calculate(const void *pvSrcData,
                           uint32_t u32SrcDataSize,
                           uint8_t au8MsgDigest[])
{
    en_result_t   enRet = ErrorInvalidParameter;
    if((pvSrcData != NULL)    &&
       (u32SrcDataSize != 0UL)  &&
       (au8MsgDigest != NULL))
    {
        /* Set HMAC Mode */

        (void)HASH_SetMode(HASH_MODE_SHA_256);
        if(HASH_Fill_Calc_Data(pvSrcData, u32SrcDataSize) == Ok)
        {
            /* Get the message digest result */
            HASH_GetResult(au8MsgDigest);
            enRet = Ok;
        }
        else
        {
            enRet = ErrorBufferFull;
        }
    }
    return enRet;
}

/**
 * @brief  HMAC calculate.
 * @param  [in] pvSrcData           Pointer to the source data buffer
 * @param  [in] u32SrcDataSize      Length of the input buffer in bytes
 * @param  [in] au8Key              Buffer of the secret key
 * @param  [in] u32KeyLength        Length of the input secret key in bytes
 * @param  [out] au8MsgDigest       Buffer of the digest data buffer. The size must be 32 bytes
 * @retval Ok: Success
 *         Error: Filling Error
 *         ErrorInvalidParameter: Parameter error
 *         ErrorTimeout: Process timeout
 */
en_result_t HMAC_Calculate(const void *pvSrcData,
                           uint32_t u32SrcDataSize,
                           const uint8_t au8Key[],
                           uint32_t u32KeyLength,
                           uint8_t au8MsgDigest[])
{
    en_result_t enRet = ErrorInvalidParameter;
    uint32_t u32TimeCount = 0UL;
    uint8_t  u8FillBuffer[HASH_GROUP_LEN] = {0UL};
    if ((pvSrcData != NULL)    &&
       (u32SrcDataSize != 0UL) &&
       (au8Key != NULL)        &&
       (u32KeyLength != 0UL)   &&
       (au8MsgDigest != NULL))
    {
        enRet = Ok;
        /* Set HMAC Mode */
        (void)HASH_SetMode(HASH_MODE_HMAC);
        if (u32KeyLength > HASH_GROUP_LEN)
        {
            SET_REG32_BIT(M4_HASH->CR, HASH_CR_LKEY);
            /* Write the key to the data register */
            (void)HASH_Fill_Calc_Data(au8Key, u32KeyLength);
        }
        else
        {
            (void)memcpy(u8FillBuffer, &au8Key[0U], u32KeyLength);
            /* Write the key to the data register */
            HASH_WriteData(u8FillBuffer);
            /* Set first group. */
            SET_REG32_BIT(M4_HASH->CR, HASH_CR_FST_GRP);
            /* Set last group. */
            SET_REG32_BIT(M4_HASH->CR, HASH_CR_KMSG_END);
            /* Start hash calculating. */
            SET_REG32_BIT(M4_HASH->CR, HASH_CR_START);
            /* Wait for operation completion */
            while(READ_REG32_BIT(M4_HASH->CR, HASH_CR_BUSY))
            {
                if(u32TimeCount++ > HASH_TIMEOUT)
                {
                    enRet = ErrorTimeout;
                    break;
                }
            }
        }
        /* Clear operation completion flag */
        CLEAR_REG32_BIT(M4_HASH->CR, HASH_CR_CYC_END);
        if (enRet == Ok)
        {
            u32TimeCount =0UL;
            /* Write the message to the data register */
            if (HASH_Fill_Calc_Data(pvSrcData, u32SrcDataSize) == Ok)
            {
                while(READ_REG32_BIT(M4_HASH->CR, HASH_CR_HMAC_END) == 0UL)
                {
                    if (u32TimeCount++ > HASH_TIMEOUT)
                    {
                        enRet = ErrorTimeout;
                        break;
                    }
                }
                if (enRet == Ok)
                {
                    /* Clear operation completion flag */
                    CLEAR_REG32_BIT(M4_HASH->CR, HASH_CR_CYC_END);
                    CLEAR_REG32_BIT(M4_HASH->CR, HASH_CR_HMAC_END);
                    /* Get the message digest result */
                    HASH_GetResult(au8MsgDigest);
                }
            }
        }
    }
    return enRet;
}

/**
 * @brief  Start HASH.
 * @param  None
 * @retval Ok: Success
 *         ErrorTimeout: Process timeout
 */
en_result_t HASH_Start(void)
{
    en_result_t enRet = Ok;
    uint32_t u32TimeCount = 0UL;
    /* Wait for the HASH to stop */
    while(READ_REG32_BIT(M4_HASH->CR, HASH_CR_START))
    {
        if (u32TimeCount++ > HASH_TIMEOUT)
        {
            enRet = ErrorTimeout;
            break;
        }
    }
    if (enRet == Ok)
    {
        /* Start hash calculating. */
        SET_REG32_BIT(M4_HASH->CR, HASH_CR_START);
    }
    return enRet;
}

/**
 * @brief  Enable or Disable HASH interrupt.
 * @param  [in] u32HashInt              Specifies the HASH interrupt to check.
 *  This parameter can be following values:
 *   @arg  HASH_INT_GROUP:              A set of data operations complete interrupt
 *   @arg  HASH_INT_ALL:                All data operations complete interrupt
 * @param  [in] enNewState              The new state of specified interrupt.
 *  This parameter can be: Enable or Disable.
 * @retval Ok: Success
 *         ErrorTimeout: Process timeout
 */
en_result_t HASH_IntCmd(uint32_t u32HashInt, en_functional_state_t enNewState)
{
    DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
    DDL_ASSERT(IS_VALID_INT_CMD(u32HashInt));
    en_result_t enRet = Ok;
    uint32_t u32TimeCount = 0UL;
    /* Wait for the HASH to stop */
    while(READ_REG32_BIT(M4_HASH->CR, HASH_CR_START))
    {
        if(u32TimeCount++ > HASH_TIMEOUT)
        {
            enRet = ErrorTimeout;
            break;
        }
    }
    if (enRet == Ok)
    {
        if (enNewState == Enable)
        {
            SET_REG32_BIT(M4_HASH->CR, u32HashInt);
        }
        else
        {
            CLEAR_REG32_BIT(M4_HASH->CR, u32HashInt);
        }
    }
    return enRet;
}

/**
 * @brief  Set mode for the HASH
 * @param  [in] u32HashMode       HASH mode selection
 *  This parameter can be one of the following values:
 *   @arg  HASH_MODE_SHA_256:     SHA_256 Operating mode
 *   @arg  HASH_MODE_HMAC:        HMAC Operating mode
 * @retval Ok: Success
 *         ErrorTimeout: Process timeout
 */
en_result_t HASH_SetMode(uint32_t u32HashMode)
{
    DDL_ASSERT(IS_VALID_MODE(u32HashMode));
    en_result_t enRet = Ok;
    uint32_t u32TimeCount = 0UL;
    /* Wait for the HASH to stop */
    while(READ_REG32_BIT(M4_HASH->CR, HASH_CR_START))
    {
        if (u32TimeCount++ > HASH_TIMEOUT)
        {
            enRet = ErrorTimeout;
            break;
        }
    }
    if (enRet == Ok)
    {
        MODIFY_REG32(M4_HASH->CR, HASH_CR_MODE, u32HashMode);
    }
    return enRet;
}

/**
 * @brief  Get HASH status
 * @param  [in] u32HashFlag           Specifies the flag to query.
 *   @arg  HASH_FLAG_START:            Operation in progress
 *   @arg  HASH_FLAG_BUSY:             Operation in progress
 *   @arg  HASH_FLAG_CYC_END:          key or message operation completed
 *   @arg  HASH_FLAG_HMAC_END:         HMAC operation completed
 * @retval Set: Flag is set
 *         Reset: Flag is reset
 */
en_flag_status_t HASH_GetStatus(uint32_t u32HashFlag)
{
    en_flag_status_t enRet;
    DDL_ASSERT(IS_VALID_FLAG(u32HashFlag));

    enRet = (READ_REG32_BIT(M4_HASH->CR, u32HashFlag) ? Set :Reset);
    return enRet;
}

/**
 * @brief  Set HASH key length
 * @param  [in] u32KeyLen             Key length.
 *  This parameter can be a value of the following:
 *   @arg  HASH_KEY_LEN_LONG:         Key length > 64 Bytes
 *   @arg  HASH_KEY_LEN_SHORT:        Key length <= 64 Bytes
 * @retval Ok: Success
 *         ErrorTimeout: Process timeout
 */
en_result_t HASH_SetKeyLength(uint32_t u32KeyLen)
{
    DDL_ASSERT(IS_VALID_KEY_LEN(u32KeyLen));
    en_result_t enRet = Ok;
    uint32_t u32TimeCount = 0UL;
    /* Wait for the HASH to stop */
    while(READ_REG32_BIT(M4_HASH->CR, HASH_CR_START))
    {
        if (u32TimeCount++ > HASH_TIMEOUT)
        {
            enRet = ErrorTimeout;
            break;
        }
    }
    if (enRet == Ok)
    {
        MODIFY_REG32(M4_HASH->CR, HASH_CR_LKEY, u32KeyLen);
    }
    return enRet;
}

/**
 * @brief  Clear HASH status
 * @param  [in] u32ClearFlag          Specifies the flag to clear.
 *  This parameter can be a value of the following:
 *   @arg  HASH_FLAG_CYC_END:         Clear the key or message operation completed flag
 *   @arg  HASH_FLAG_HMAC_END:        Clear the HMAC operation completed flag
 * @retval Ok: Success
 *         ErrorTimeout: Process timeout
 */
en_result_t HASH_ClearStatus(uint32_t u32ClearFlag)
{
    en_result_t enRet = Ok;
    uint32_t u32TimeCount = 0UL;
    DDL_ASSERT(IS_VALID_FLAG_CLR(u32ClearFlag));

    /* Wait for the HASH to stop */
    while(READ_REG32_BIT(M4_HASH->CR, HASH_CR_START))
    {
        if (u32TimeCount++ > HASH_TIMEOUT)
        {
            enRet = ErrorTimeout;
            break;
        }
    }
    if (enRet == Ok)
    {
        CLEAR_REG32_BIT(M4_HASH->CR, u32ClearFlag);
    }
    return enRet;
}

/**
 * @brief  Set trigger source for HASH
 * @param  [in] enSrc                   Specifies the Event as trigger source.
 *  This parameter can be a value of the following:
 *   @arg  HASH_TRG_SRC_DMA1_BTC0:      Select the DMA1 channel_0 block transfer complete as trigger source
 *   @arg  HASH_TRG_SRC_DMA1_BTC1:      Select the DMA1 channel_1 block transfer complete as trigger source
 *   @arg  HASH_TRG_SRC_DMA1_BTC2:      Select the DMA1 channel_2 block transfer complete as trigger source
 *   @arg  HASH_TRG_SRC_DMA1_BTC3:      Select the DMA1 channel_3 block transfer complete as trigger source
 *   @arg  HASH_TRG_SRC_DMA1_BTC4:      Select the DMA1 channel_4 block transfer complete as trigger source
 *   @arg  HASH_TRG_SRC_DMA1_BTC5:      Select the DMA1 channel_5 block transfer complete as trigger source
 *   @arg  HASH_TRG_SRC_DMA1_BTC6:      Select the DMA1 channel_6 block transfer complete as trigger source
 *   @arg  HASH_TRG_SRC_DMA1_BTC7:      Select the DMA1 channel_7 block transfer complete as trigger source
 *   @arg  HASH_TRG_SRC_DMA1_TC0:       Select the DMA1 channel_0 transfer complete as trigger source
 *   @arg  HASH_TRG_SRC_DMA1_TC1:       Select the DMA1 channel_1 transfer complete as trigger source
 *   @arg  HASH_TRG_SRC_DMA1_TC2:       Select the DMA1 channel_2 transfer complete as trigger source
 *   @arg  HASH_TRG_SRC_DMA1_TC3:       Select the DMA1 channel_3 transfer complete as trigger source
 *   @arg  HASH_TRG_SRC_DMA1_TC4:       Select the DMA1 channel_4 transfer complete as trigger source
 *   @arg  HASH_TRG_SRC_DMA1_TC5:       Select the DMA1 channel_5 transfer complete as trigger source
 *   @arg  HASH_TRG_SRC_DMA1_TC6:       Select the DMA1 channel_6 transfer complete as trigger source
 *   @arg  HASH_TRG_SRC_DMA1_TC7:       Select the DMA1 channel_7 transfer complete as trigger source
 *   @arg  HASH_TRG_SRC_DMA2_BTC0:      Select the DMA2 channel_0 block transfer complete as trigger source
 *   @arg  HASH_TRG_SRC_DMA2_BTC1:      Select the DMA2 channel_1 block transfer complete as trigger source
 *   @arg  HASH_TRG_SRC_DMA2_BTC2:      Select the DMA2 channel_2 block transfer complete as trigger source
 *   @arg  HASH_TRG_SRC_DMA2_BTC3:      Select the DMA2 channel_3 block transfer complete as trigger source
 *   @arg  HASH_TRG_SRC_DMA2_BTC4:      Select the DMA2 channel_4 block transfer complete as trigger source
 *   @arg  HASH_TRG_SRC_DMA2_BTC5:      Select the DMA2 channel_5 block transfer complete as trigger source
 *   @arg  HASH_TRG_SRC_DMA2_BTC6:      Select the DMA2 channel_6 block transfer complete as trigger source
 *   @arg  HASH_TRG_SRC_DMA2_BTC7:      Select the DMA2 channel_7 block transfer complete as trigger source
 *   @arg  HASH_TRG_SRC_DMA2_TC0:       Select the DMA2 channel_0 transfer complete as trigger source
 *   @arg  HASH_TRG_SRC_DMA2_TC1:       Select the DMA2 channel_1 transfer complete as trigger source
 *   @arg  HASH_TRG_SRC_DMA2_TC2:       Select the DMA2 channel_2 transfer complete as trigger source
 *   @arg  HASH_TRG_SRC_DMA2_TC3:       Select the DMA2 channel_3 transfer complete as trigger source
 *   @arg  HASH_TRG_SRC_DMA2_TC4:       Select the DMA2 channel_4 transfer complete as trigger source
 *   @arg  HASH_TRG_SRC_DMA2_TC5:       Select the DMA2 channel_5 transfer complete as trigger source
 *   @arg  HASH_TRG_SRC_DMA2_TC6:       Select the DMA2 channel_6 transfer complete as trigger source
 *   @arg  HASH_TRG_SRC_DMA2_TC7:       Select the DMA2 channel_7 transfer complete as trigger source
 * @retval None
 */
void HASH_SetTriggerSrc(en_event_src_t enSrc)
{
    DDL_ASSERT(IS_VALID_TRG_SRC_SEL(enSrc));

    if(((enSrc >= HASH_TRG_SRC_DMA1_TC0) && (enSrc <= HASH_TRG_SRC_DMA1_TC7)) ||  \
       ((enSrc >= HASH_TRG_SRC_DMA2_TC0) && (enSrc <= HASH_TRG_SRC_DMA2_TC7)))
    {
        MODIFY_REG32(M4_AOS->HASH_ITRGSELA, AOS_HASH_ITRGSELA_TRGSEL, enSrc);
    }
    else
    {
        MODIFY_REG32(M4_AOS->HASH_ITRGSELB, AOS_HASH_ITRGSELB_TRGSEL, enSrc);
    }
}

/**
 * @brief  Enable or Disable common trigger source for HASH
 * @param  [in] u8TrigReg           HASH common trigger source select.
 *         This parameter can be a value of @ref HASH_Common_Trigger_Reg_Sel
 *   @arg  HASH_TRIG_REG_BLKCOM:    DMA block transfer complete register.
 *   @arg  HASH_TRID_REG_TRNCOM:    DMA transfer complete register
 * @param  [in] u32ComTrig          Common trigger event enable bit mask.
 *         This parameter can be value of @ref HASH_Common_Trigger_Sel
 *   @arg  HASH_COM_TRIG1:          Common trigger source 1.
 *   @arg  HASH_COM_TRIG2:          Common trigger source 2.
 * @param  [in] enNewState          Disable or Enable the function
 * @retval None
 */
void HASH_ComTriggerCmd(uint8_t u8TrigReg, uint32_t u32ComTrig,
                        en_functional_state_t enNewState)
{
    DDL_ASSERT(IS_VALID_TRG_REG_SEL(u8TrigReg));
    DDL_ASSERT(IS_VALID_COM_TRIG(u32ComTrig));
    DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
    __IO uint32_t *HASH_ITRGSELx = (__IO uint32_t *)((uint32_t)&M4_AOS->HASH_ITRGSELA +  4UL * u8TrigReg);

    if (enNewState == Enable)
    {
        SET_REG32_BIT(*HASH_ITRGSELx, u32ComTrig);
    }
    else
    {
        CLEAR_REG32_BIT(*HASH_ITRGSELx, u32ComTrig);
    }
}

/**
 * @brief  Set the group of messages.
 * @param  [in] u32MsgGroup       First group or Last group of messages.
 *  This parameter can be a value of the following:
 *   @arg  HASH_MSG_GRP_FIRST:    The first group of messages or keys
 *   @arg  HASH_MSG_GRP_END:      The last group of messages or keys
 *   @arg  HASH_MSG_GRP_ONLY_ONE: Only one set of message or key
 * @retval Ok: Success
 *         ErrorTimeout: Process timeout
 */
en_result_t HASH_MsgGrpConfig(uint32_t u32MsgGroup)
{
    DDL_ASSERT(IS_VALID_MSG_GRP(u32MsgGroup));
    en_result_t enRet = Ok;
    uint32_t u32TimeCount = 0UL;
    /* Wait for the HASH to stop */
    while(READ_REG32_BIT(M4_HASH->CR, HASH_CR_START))
    {
        if (u32TimeCount++ > HASH_TIMEOUT)
        {
            enRet = ErrorTimeout;
            break;
        }
    }
    if (enRet == Ok)
    {
        SET_REG32_BIT(M4_HASH->CR, u32MsgGroup);
    }
    return enRet;
}

/**
 * @brief  Provides the message digest result.
 * @param  [out] au8MsgDigest       Buffer for message digest.
 * @retval None
 */
void HASH_GetResult(uint8_t au8MsgDigest[])
{
    uint8_t  i;
    uint32_t u32Temp1;
    uint32_t u32HashHr = (uint32_t)(&M4_HASH->HR7);
    uint32_t u32DigestHr = (uint32_t)(&au8MsgDigest[0U]);
    for (i = 0U; i < 8U; i++)
    {
        u32Temp1 = __REV(RW_MEM32(u32HashHr));
        *(uint32_t *)(u32DigestHr) = u32Temp1;
        u32HashHr += 4U;
        u32DigestHr += 4U;
    }
}

/**
 * @brief  HASH Filling data
 * @param  [in] au8Data              The source data buffer
 * @param  [in] u32DataSize          Length of the input buffer in bytes
 * @retval Ok: Success
 *         ErrorTimeout: Process timeout
 */
static en_result_t HASH_Fill_Calc_Data(const uint8_t au8Data[], uint32_t u32DataSize)
{
    en_result_t enRet = Ok;
    uint8_t  au8FillBuffer[HASH_GROUP_LEN];
    uint8_t  u8FirstGroup = 0U;
    uint8_t  u8LastGroup = 0U;
    uint8_t  u8FillFlag = 0U;
    uint32_t u32TimeCount = 0UL;
    uint32_t u32GroupCount = 0UL;
    uint32_t u32BitLenHi;
    uint32_t u32BitLenLo;
    uint32_t u32Index;
    u32BitLenHi    = (u32DataSize >> 29UL) & 0x7UL;
    u32BitLenLo    = (u32DataSize << 3UL);
    while(u32DataSize > 0UL)
    {
        /* Wait for the HASH to stop */
        while(READ_REG32_BIT(M4_HASH->CR, HASH_CR_START))
        {
            if(u32TimeCount++ > HASH_TIMEOUT)
            {
                enRet = ErrorTimeout;
                break;
            }
        }
        if (enRet == Ok)
        {
            u32Index = u32GroupCount * HASH_GROUP_LEN;
            if((u32DataSize >= HASH_GROUP_LEN))
            {
                (void)memset(au8FillBuffer, 0, HASH_GROUP_LEN);
                (void)memcpy(au8FillBuffer, &au8Data[u32Index], HASH_GROUP_LEN);
                HASH_WriteData(au8FillBuffer);
                u32GroupCount++;
                u32DataSize -= HASH_GROUP_LEN;
            }
            else
            {
                (void)memset(au8FillBuffer, 0, HASH_GROUP_LEN);
                if(u32DataSize >= LAST_GROUP_MAX_LEN)
                {
                    if(u8FillFlag == 0U)
                    {
                        (void)memcpy(au8FillBuffer, &au8Data[u32Index], u32DataSize);
                        au8FillBuffer[u32DataSize] = 0x80U;
                        u8FillFlag = 1U;
                    }
                    else
                    {
                        u32DataSize = 0UL;
                    }
                }
                else
                {
                    (void)memcpy(au8FillBuffer, &au8Data[u32Index], u32DataSize);
                    au8FillBuffer[u32DataSize] = 0x80U;
                    u32DataSize = 0UL;
                }
                if(0U == u32DataSize)
                {
                    au8FillBuffer[63U] = (uint8_t)(u32BitLenLo);
                    au8FillBuffer[62U] = (uint8_t)(u32BitLenLo >> 8U);
                    au8FillBuffer[61U] = (uint8_t)(u32BitLenLo >> 16U);
                    au8FillBuffer[60U] = (uint8_t)(u32BitLenLo >> 24U);
                    au8FillBuffer[59U] = (uint8_t)(u32BitLenHi);
                    au8FillBuffer[58U] = (uint8_t)(u32BitLenHi >> 8U);
                    au8FillBuffer[57U] = (uint8_t)(u32BitLenHi >> 16U);
                    au8FillBuffer[56U] = (uint8_t)(u32BitLenHi >> 24U);
                    u8LastGroup = 1U;
                }
                HASH_WriteData(au8FillBuffer);
            }
            /* check if first group */
            if (0U == u8FirstGroup)
            {
                u8FirstGroup = 1U;
                /* Set first group. */
                SET_REG32_BIT(M4_HASH->CR, HASH_CR_FST_GRP);
            }
            /* check if last group */
            if (1U == u8LastGroup)
            {
                u8LastGroup = 0U;
                /* Set last group. */
                SET_REG32_BIT(M4_HASH->CR, HASH_CR_KMSG_END);
            }
            /* Start hash calculating. */
            SET_REG32_BIT(M4_HASH->CR, HASH_CR_START);
            /* Wait for operation completion */
            while(READ_REG32_BIT(M4_HASH->CR, HASH_CR_BUSY))
            {
                if(u32TimeCount++ > HASH_TIMEOUT)
                {
                    enRet = ErrorTimeout;
                    break;
                }
            }
        }
    }
    return enRet;
}

/**
 * @brief  Writes the input buffer in data register.
 * @param  [in] au8Data       The buffer for source data
 * @retval None
 */
static void HASH_WriteData(uint8_t au8Data[])
{
    uint8_t  i;
    uint32_t u32Temp1;
    uint32_t u32HashDr = (uint32_t)&(M4_HASH->DR15);

    for (i = 0U; i < 16U; i++)
    {
        u32Temp1 = __REV(RW_MEM32(&au8Data[i*4U]));
        RW_MEM32(u32HashDr) = u32Temp1;
        u32HashDr += 4U;
    }
}

/**
 * @}
 */

#endif /* DDL_HASH_ENABLE */

/**
 * @}
 */

/**
* @}
*/
/*******************************************************************************
 * EOF (not truncated)
 ******************************************************************************/