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