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