1 /**************************************************************************//**
2 * @file trng.c
3 * @version V3.00
4 * @brief M2L31 series TRNG driver source file
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 TRNG_Driver TRNG Driver
18 @{
19 */
20
21 /** @addtogroup TRNG_EXPORTED_FUNCTIONS TRNG Exported Functions
22 @{
23 */
24
25 /**
26 * @brief Initialize TRNG hardware.
27 * @return TRNG hardware enable success or failed.
28 * @retval 0 Success
29 * @retval -1 Time-out. TRNG hardware may not be enabled.
30 */
TRNG_Open(void)31 int32_t TRNG_Open(void)
32 {
33 uint32_t u32TimeOutCount;
34
35 /* Reset TRNG */
36 SYS->IPRST1 |= SYS_IPRST1_TRNGRST_Msk;
37 SYS->IPRST1 ^= SYS_IPRST1_TRNGRST_Msk;
38
39 /* Enable TRNG Power */
40 TRNG->CTL = TRNG_CTL_LDOEN_Msk;
41
42 /* Waiting for ready */
43 u32TimeOutCount = SystemCoreClock;
44 while((TRNG->STS & (TRNG_STS_LDORDY_Msk)) == 0)
45 {
46 if(--u32TimeOutCount == 0) return -1; /* Time-out error */
47 }
48
49 /* Eanble TRNG and release reset */
50 TRNG->CTL = TRNG_CTL_TRNGEN_Msk | TRNG_CTL_LDOEN_Msk | TRNG_CTL_NRST_Msk;
51
52 /* Waiting for ready */
53 u32TimeOutCount = SystemCoreClock;
54 while ((TRNG->STS & (TRNG_STS_TRNGRDY_Msk)) == 0)
55 {
56 if(--u32TimeOutCount == 0) return -1; /* Time-out error */
57 }
58
59 TRNG->CTL = TRNG_CTL_TRNGEN_Msk | TRNG_CTL_LDOEN_Msk | TRNG_CTL_NRST_Msk | TRNG_CTL_INSTANT_Msk |
60 TRNG_CTL_RESEED_Msk | TRNG_CTL_UPDATE_Msk | TRNG_CTL_START_Msk;
61
62 /* Waiting for DVIF */
63 u32TimeOutCount = SystemCoreClock;
64 while((TRNG->STS & (TRNG_STS_DVIF_Msk)) == 0)
65 {
66 if(--u32TimeOutCount == 0) return -1; /* Time-out error */
67 }
68
69 return 0;
70 }
71
72 /**
73 * @brief Generate a 32-bits random number word.
74 * @param[out] u32RndNum The output 32-bits word random number.
75 *
76 * @return Success or time-out.
77 * @retval 0 Success
78 * @retval -1 Time-out. TRNG hardware may not be enabled.
79 */
TRNG_GenWord(uint32_t * u32RndNum)80 int32_t TRNG_GenWord(uint32_t *u32RndNum)
81 {
82 uint32_t i, u32Reg, timeout;
83
84 *u32RndNum = 0;
85
86 TRNG->CTL |= TRNG_CTL_START_Msk;
87
88 for(timeout = SystemCoreClock; timeout > 0; timeout--)
89 {
90 if(TRNG->STS & TRNG_STS_DVIF_Msk)
91 break;
92 }
93
94 if(timeout == 0)
95 return -1;
96
97 *u32RndNum = TRNG->DATA[0];
98
99 return 0;
100 }
101
102 /**
103 * @brief Generate a big number in binary format.
104 * @param[out] u8BigNum The output big number.
105 * @param[in] i32Len Request bit length of the output big number. It must be multiple of 8.
106 *
107 * @return Success or time-out.
108 * @retval 0 Success
109 * @retval -1 Time-out. TRNG hardware may not be enabled.
110 */
TRNG_GenBignum(uint8_t u8BigNum[],int32_t i32Len)111 int32_t TRNG_GenBignum(uint8_t u8BigNum[], int32_t i32Len)
112 {
113 uint32_t i, j, u32Reg, timeout;
114
115 for (i = 0; i < i32Len/8; i++)
116 {
117 /* Get 32 random bits */
118 if((i & 0x3) == 0)
119 {
120 TRNG->CTL |= TRNG_CTL_START_Msk;
121
122 /* Return fail when timeout */
123 for(timeout = (CLK_GetHCLKFreq() / 100); timeout > 0; timeout--)
124 {
125 if(TRNG->CTL & TRNG_STS_DVIF_Msk)
126 break;
127 }
128
129 if(timeout == 0)
130 return -1;
131
132 u32Reg = TRNG->DATA[0];
133 j = 0;
134 }
135
136 u8BigNum[i] = (u32Reg >> (j * 8)) & 0xff;
137 j++;
138 }
139
140 return 0;
141 }
142
143 /**
144 * @brief Generate a big number in hex format.
145 * @param[out] cBigNumHex The output hex format big number.
146 * @param[in] i32Len Request bit length of the output big number. It must be multiple of 8.
147 *
148 * @return Success or time-out.
149 * @retval 0 Success
150 * @retval -1 Time-out. TRNG hardware may not be enabled.
151 */
TRNG_GenBignumHex(char cBigNumHex[],int32_t i32Len)152 int32_t TRNG_GenBignumHex(char cBigNumHex[], int32_t i32Len)
153 {
154 uint32_t i, j, u32Reg, timeout, ch,cl;
155
156 for(i = 0; i < i32Len / 8; i++)
157 {
158 /* Get 32 random bits */
159 if((i & 0x3) == 0)
160 {
161 TRNG->CTL |= TRNG_CTL_START_Msk;
162
163 /* Return fail when timeout */
164 for(timeout = (CLK_GetHCLKFreq() / 100); timeout > 0; timeout--)
165 {
166 if(TRNG->CTL & TRNG_STS_DVIF_Msk)
167 break;
168 }
169
170 if(timeout == 0)
171 return -1;
172
173 u32Reg = TRNG->DATA[0];
174 j = 0;
175 }
176
177 ch = ((u32Reg >> (j * 8)) & 0xf0) >> 4;
178 cl = (u32Reg >> (j * 8)) & 0x0f;
179 j++;
180
181 if(ch >= 0xa)
182 cBigNumHex[i * 2] = ch - 0xa + 'a';
183 else
184 cBigNumHex[i * 2] = ch + '0';
185
186 if(cl >= 0xa)
187 cBigNumHex[i * 2 + 1] = cl - 0xa + 'a';
188 else
189 cBigNumHex[i * 2 + 1] = cl + '0';
190
191 }
192
193 return 0;
194 }
195
196 /*@}*/ /* end of group TRNG_EXPORTED_FUNCTIONS */
197
198 /*@}*/ /* end of group TRNG_Driver */
199
200 /*@}*/ /* end of group Standard_Driver */
201
202 /*** (C) COPYRIGHT 2023 Nuvoton Technology Corp. ***/
203
204