1 /**************************************************************************//**
2  * @file     trng.c
3  * @version  V3.00
4  * @brief    M460 series TRNG driver source file
5  *
6  * @copyright SPDX-License-Identifier: Apache-2.0
7  * @copyright Copyright (C) 2021 Nuvoton Technology Corp. All rights reserved.
8 *****************************************************************************/
9 
10 #include <stdio.h>
11 
12 #include "NuMicro.h"
13 
14 
15 /** @addtogroup Standard_Driver Standard Driver
16   @{
17 */
18 
19 /** @addtogroup TRNG_Driver TRNG Driver
20   @{
21 */
22 
23 
24 /** @addtogroup TRNG_EXPORTED_FUNCTIONS TRNG Exported Functions
25   @{
26 */
27 
28 
29 /**
30   * @brief Initialize TRNG hardware.
31   * @return  TRNG hardware enable success or failed.
32   * @retval  0   Success
33   * @retval  -1  Time-out. TRNG hardware may not be enabled.
34   */
TRNG_Open(void)35 int32_t TRNG_Open(void)
36 {
37     uint32_t u32TimeOutCount = SystemCoreClock; /* 1 second time-out */
38 
39     SYS->IPRST1 |= SYS_IPRST1_TRNGRST_Msk;
40     SYS->IPRST1 ^= SYS_IPRST1_TRNGRST_Msk;
41 
42     TRNG->CTL |= TRNG_CTL_TRNGEN_Msk;
43 
44     TRNG->ACT |= TRNG_ACT_ACT_Msk;
45 
46     /* Waiting for ready */
47     while ((TRNG->CTL & TRNG_CTL_READY_Msk) == 0)
48     {
49         if(--u32TimeOutCount == 0) return -1; /* Time-out error */
50     }
51 
52     return 0;
53 }
54 
55 
56 /**
57   * @brief   Generate a 32-bits random number word.
58   * @param[out]  u32RndNum    The output 32-bits word random number.
59   *
60   * @return  Success or time-out.
61   * @retval  0   Success
62   * @retval  -1  Time-out. TRNG hardware may not be enabled.
63   */
TRNG_GenWord(uint32_t * u32RndNum)64 int32_t TRNG_GenWord(uint32_t *u32RndNum)
65 {
66     uint32_t   i, u32Reg, timeout;
67 
68     *u32RndNum = 0;
69     u32Reg = TRNG->CTL;
70 
71     for (i = 0; i < 4; i++)
72     {
73         TRNG->CTL = TRNG_CTL_TRNGEN_Msk | u32Reg;
74 
75         /* TRNG should generate one byte per 125*8 us */
76         for (timeout = (CLK_GetHCLKFreq() / 100); timeout > 0; timeout--)
77         {
78             if (TRNG->CTL & TRNG_CTL_DVIF_Msk)
79                 break;
80         }
81 
82         if (timeout == 0)
83             return -1;
84 
85         *u32RndNum |= ((TRNG->DATA & 0xff) << i*8);
86 
87     }
88     return 0;
89 }
90 
91 /**
92   * @brief   Generate a big number in binary format.
93   * @param[out]  u8BigNum  The output big number.
94   * @param[in]   i32Len    Request bit length of the output big number. It must be multiple of 8.
95   *
96   * @return  Success or time-out.
97   * @retval  0   Success
98   * @retval  -1  Time-out. TRNG hardware may not be enabled.
99   */
TRNG_GenBignum(uint8_t u8BigNum[],int32_t i32Len)100 int32_t TRNG_GenBignum(uint8_t u8BigNum[], int32_t i32Len)
101 {
102     uint32_t   i, u32Reg, timeout;
103 
104     u32Reg = TRNG->CTL;
105 
106     for (i = 0; i < i32Len/8; i++)
107     {
108         TRNG->CTL = TRNG_CTL_TRNGEN_Msk | u32Reg;
109 
110         /* TRNG should generate one byte per 125*8 us */
111         for (timeout = (CLK_GetHCLKFreq() / 100); timeout > 0; timeout--)
112         {
113             if (TRNG->CTL & TRNG_CTL_DVIF_Msk)
114                 break;
115         }
116 
117         if (timeout == 0)
118             return -1;
119 
120         u8BigNum[i] = (TRNG->DATA & 0xff);
121     }
122     return 0;
123 }
124 
125 /**
126   * @brief   Generate a big number in hex format.
127   * @param[out]  cBigNumHex  The output hex format big number.
128   * @param[in]   i32Len      Request bit length of the output big number. It must be multiple of 8.
129   *
130   * @return  Success or time-out.
131   * @retval  0   Success
132   * @retval  -1  Time-out. TRNG hardware may not be enabled.
133   */
TRNG_GenBignumHex(char cBigNumHex[],int32_t i32Len)134 int32_t TRNG_GenBignumHex(char cBigNumHex[], int32_t i32Len)
135 {
136     uint32_t   i, idx, u32Reg, timeout;
137     uint32_t   data;
138 
139     u32Reg = TRNG->CTL;
140     idx = 0;
141     for (i = 0; i < i32Len/8; i++)
142     {
143         TRNG->CTL = TRNG_CTL_TRNGEN_Msk | u32Reg;
144 
145         /* TRNG should generate one byte per 125*8 us */
146         for (timeout = (CLK_GetHCLKFreq() / 100); timeout > 0; timeout--)
147         {
148             if (TRNG->CTL & TRNG_CTL_DVIF_Msk)
149                 break;
150         }
151 
152         if (timeout == 0)
153             return -1;
154 
155         data = (TRNG->DATA & 0xff);
156 
157         if (data >= 0xA0)
158             cBigNumHex[idx++] = ((data >> 4) & 0xf) - 10 + 'A';
159         else
160             cBigNumHex[idx++] = ((data >> 4) & 0xf) + '0';
161 
162         data &= 0xf;
163         if (data >= 0xA)
164             cBigNumHex[idx++] = data - 10 + 'A';
165         else
166             cBigNumHex[idx++] = data + '0';
167     }
168     cBigNumHex[idx] = 0;
169     return 0;
170 }
171 
172 
173 /*@}*/ /* end of group TRNG_EXPORTED_FUNCTIONS */
174 
175 /*@}*/ /* end of group TRNG_Driver */
176 
177 /*@}*/ /* end of group Standard_Driver */
178