1 /**************************************************************************//** 2 * @file rng.c 3 * @version V3.00 4 * @brief Show how to get true random number. 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 RNG_Driver RNG Driver 18 @{ 19 */ 20 21 /** @addtogroup RNG_EXPORTED_FUNCTIONS RNG Exported Functions 22 @{ 23 */ 24 25 /** 26 * @brief Open random number generator 27 * 28 * @return 0 Successful 29 * -1 Failed 30 * 31 * @details The function is used to disable rng interrupt. 32 */ RNG_Open(void)33int32_t RNG_Open(void) 34 { 35 int32_t i; 36 int32_t timeout = 0x1000000; 37 38 /* TRNG LDO Enable */ 39 TRNG->CTL |= TRNG_CTL_LDOEN_Msk; 40 41 /* Waiting for ready */ 42 i = 0; 43 while((TRNG->STS & (TRNG_STS_LDORDY_Msk)) != (TRNG_STS_LDORDY_Msk)) 44 { 45 if(i++ > timeout) 46 { 47 /* LDO ready timeout */ 48 return -1; 49 } 50 } 51 52 /* TRNG Enable */ 53 TRNG->CTL |= TRNG_CTL_NRST_Msk | TRNG_CTL_TRNGEN_Msk; 54 55 /* Waiting for ready */ 56 i = 0; 57 while((TRNG->STS & (TRNG_STS_TRNGRDY_Msk)) != (TRNG_STS_TRNGRDY_Msk)) 58 { 59 if(i++ > timeout) 60 { 61 /* TRNG ready timeout */ 62 return -1; 63 } 64 } 65 66 return 0; 67 } 68 69 70 /** 71 * @brief Get random words 72 * 73 * @param[in] pu32Buf Buffer pointer to store the random number 74 * 75 * @param[in] i32WordCnt Buffer size in word count. i32WordCnt must <= 8 76 * 77 * @return Word count of random number in buffer 78 * 79 * @details The function is used to generate random numbers 80 */ RNG_Random(uint32_t * pu32Buf,int32_t i32WordCnt)81int32_t RNG_Random(uint32_t *pu32Buf, int32_t i32WordCnt) 82 { 83 int32_t i; 84 int32_t timeout = 0x10000; 85 86 i = 0; 87 do 88 { 89 /* Start DRBG */ 90 TRNG->CTL |= TRNG_CTL_MODE_DRBG | TRNG_CTL_START_Msk; 91 92 /* Waiting for Busy */ 93 while((TRNG->STS & TRNG_STS_DVIF_Msk) == 0) 94 { 95 if(timeout-- < 0) 96 return 0; 97 } 98 99 pu32Buf[i++] = TRNG->DATA[0]; 100 if(--i32WordCnt <= 0) break; 101 pu32Buf[i++] = TRNG->DATA[1]; 102 if(--i32WordCnt <= 0) break; 103 pu32Buf[i++] = TRNG->DATA[2]; 104 if(--i32WordCnt <= 0) break; 105 pu32Buf[i++] = TRNG->DATA[3]; 106 if(--i32WordCnt <= 0) break; 107 108 } 109 while(i32WordCnt); 110 111 return i; 112 } 113 114 /** 115 * @brief To generate entropy from hardware entropy source (TRNG) 116 * 117 * @param[in] pu8Out Output buffer for the entropy 118 * @param[in] i32Len Entropy length in bytes 119 * @return -1 Failed 120 * Others The bytes in pu8Out buffer 121 * 122 * @details The function is used to generate entropy from TRNG. 123 */ RNG_EntropyPoll(uint8_t * pu8Out,int32_t i32Len)124int32_t RNG_EntropyPoll(uint8_t* pu8Out, int32_t i32Len) 125 { 126 int32_t timeout; 127 int32_t i,cnt, len; 128 uint32_t u32Entropy; 129 130 if((TRNG->STS & (TRNG_STS_LDORDY_Msk | TRNG_STS_TRNGRDY_Msk)) != (TRNG_STS_LDORDY_Msk | TRNG_STS_TRNGRDY_Msk)) 131 { 132 /* TRNG is not in active */ 133 printf("trng is not active\n"); 134 return -1; 135 } 136 137 len = i32Len; 138 cnt = (len + 3) / 4; 139 for(i = 0; i < cnt; i++) 140 { 141 /* Trigger entropy generate */ 142 TRNG->CTL |= TRNG_CTL_START_Msk; 143 144 timeout = SystemCoreClock; 145 while((TRNG->STS & TRNG_STS_DVIF_Msk) == 0) 146 { 147 if(timeout-- <= 0) 148 { 149 /* Timeout error */ 150 printf("timeout\n"); 151 return -1; 152 } 153 } 154 /* Get one byte entroy */ 155 u32Entropy = TRNG->DATA[0]; 156 *pu8Out++ = u32Entropy & 0xff; 157 if(len-- <= 0) break; 158 *pu8Out++ = (u32Entropy >> 8) & 0xff; 159 if(len-- <= 0) break; 160 *pu8Out++ = (u32Entropy >> 16) & 0xff; 161 if(len-- <= 0) break; 162 *pu8Out++ = (u32Entropy >> 24) & 0xff; 163 if(len-- <= 0) break; 164 } 165 166 return i32Len; 167 } 168 169 /**@}*/ /* end of group RNG_EXPORTED_FUNCTIONS */ 170 171 /**@}*/ /* end of group RNG_Driver */ 172 173 /**@}*/ /* end of group Standard_Driver */ 174 175