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