1 /**************************************************************************//**
2  * @file     rng.c
3  * @version  V3.00
4  * @brief    Show how to get true random number.
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  * @copyright (C) 2023 Nuvoton Technology Corp. All rights reserved.
8  *****************************************************************************/
9 
10 #include <stdio.h>
11 #include "NuMicro.h"
12 
13 /** @addtogroup Standard_Driver Standard Driver
14   @{
15 */
16 
17 /** @addtogroup RNG_Driver RNG Driver
18   @{
19 */
20 
21 /** @addtogroup RNG_EXPORTED_FUNCTIONS RNG Exported Functions
22   @{
23 */
24 
25 /**
26  *  @brief      Open random number generator
27  *
28  *  @return      0  Successful
29  *              -1  Failed
30  *
31  *  @details    The function is used to disable rng interrupt.
32  */
RNG_Open(void)33 int32_t RNG_Open(void)
34 {
35     int32_t i;
36     int32_t timeout = 0x1000000;
37 
38     /* TRNG LDO Enable */
39     TRNG->CTL |= TRNG_CTL_LDOEN_Msk;
40 
41     /* Waiting for ready */
42     i = 0;
43     while((TRNG->STS & (TRNG_STS_LDORDY_Msk)) != (TRNG_STS_LDORDY_Msk))
44     {
45         if(i++ > timeout)
46         {
47             /* LDO ready timeout */
48             return -1;
49         }
50     }
51 
52     /* TRNG Enable */
53     TRNG->CTL |= TRNG_CTL_NRST_Msk | TRNG_CTL_TRNGEN_Msk;
54 
55     /* Waiting for ready */
56     i = 0;
57     while((TRNG->STS & (TRNG_STS_TRNGRDY_Msk)) != (TRNG_STS_TRNGRDY_Msk))
58     {
59         if(i++ > timeout)
60         {
61             /* TRNG ready timeout */
62             return -1;
63         }
64     }
65 
66     return 0;
67 }
68 
69 
70 /**
71  *  @brief      Get random words
72  *
73  *  @param[in]  pu32Buf Buffer pointer to store the random number
74  *
75  *  @param[in]  i32WordCnt  Buffer size in word count. i32WordCnt must <= 8
76  *
77  *  @return     Word count of random number in buffer
78  *
79  *  @details    The function is used to generate random numbers
80  */
RNG_Random(uint32_t * pu32Buf,int32_t i32WordCnt)81 int32_t RNG_Random(uint32_t *pu32Buf, int32_t i32WordCnt)
82 {
83     int32_t i;
84     int32_t timeout = 0x10000;
85 
86     i = 0;
87     do
88     {
89         /* Start DRBG */
90         TRNG->CTL |= TRNG_CTL_MODE_DRBG | TRNG_CTL_START_Msk;
91 
92         /* Waiting for Busy */
93         while((TRNG->STS & TRNG_STS_DVIF_Msk) == 0)
94         {
95             if(timeout-- < 0)
96                 return 0;
97         }
98 
99         pu32Buf[i++] = TRNG->DATA[0];
100         if(--i32WordCnt <= 0) break;
101         pu32Buf[i++] = TRNG->DATA[1];
102         if(--i32WordCnt <= 0) break;
103         pu32Buf[i++] = TRNG->DATA[2];
104         if(--i32WordCnt <= 0) break;
105         pu32Buf[i++] = TRNG->DATA[3];
106         if(--i32WordCnt <= 0) break;
107 
108     }
109     while(i32WordCnt);
110 
111     return i;
112 }
113 
114 /**
115  *  @brief      To generate entropy from hardware entropy source (TRNG)
116  *
117  *  @param[in]  pu8Out     Output buffer for the entropy
118  *  @param[in]  i32Len     Entropy length in bytes
119  *  @return     -1       Failed
120  *               Others  The bytes in pu8Out buffer
121  *
122  *  @details    The function is used to generate entropy from TRNG.
123  */
RNG_EntropyPoll(uint8_t * pu8Out,int32_t i32Len)124 int32_t RNG_EntropyPoll(uint8_t* pu8Out, int32_t i32Len)
125 {
126     int32_t timeout;
127     int32_t i,cnt, len;
128     uint32_t u32Entropy;
129 
130     if((TRNG->STS & (TRNG_STS_LDORDY_Msk | TRNG_STS_TRNGRDY_Msk)) != (TRNG_STS_LDORDY_Msk | TRNG_STS_TRNGRDY_Msk))
131     {
132         /* TRNG is not in active */
133         printf("trng is not active\n");
134         return -1;
135     }
136 
137     len = i32Len;
138     cnt = (len + 3) / 4;
139     for(i = 0; i < cnt; i++)
140     {
141         /* Trigger entropy generate */
142         TRNG->CTL |= TRNG_CTL_START_Msk;
143 
144         timeout = SystemCoreClock;
145         while((TRNG->STS & TRNG_STS_DVIF_Msk) == 0)
146         {
147             if(timeout-- <= 0)
148             {
149                 /* Timeout error */
150                 printf("timeout\n");
151                 return -1;
152             }
153         }
154         /* Get one byte entroy */
155         u32Entropy = TRNG->DATA[0];
156         *pu8Out++ = u32Entropy & 0xff;
157         if(len-- <= 0) break;
158         *pu8Out++ = (u32Entropy >>  8) & 0xff;
159         if(len-- <= 0) break;
160         *pu8Out++ = (u32Entropy >> 16) & 0xff;
161         if(len-- <= 0) break;
162         *pu8Out++ = (u32Entropy >> 24) & 0xff;
163         if(len-- <= 0) break;
164     }
165 
166     return i32Len;
167 }
168 
169 /**@}*/ /* end of group RNG_EXPORTED_FUNCTIONS */
170 
171 /**@}*/ /* end of group RNG_Driver */
172 
173 /**@}*/ /* end of group Standard_Driver */
174 
175