VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/MdePkg/Library/BaseRngLibTimerLib/RngLibTimer.c@ 105668

Last change on this file since 105668 was 99404, checked in by vboxsync, 2 years ago

Devices/EFI/FirmwareNew: Update to edk2-stable202302 and make it build, bugref:4643

  • Property svn:eol-style set to native
File size: 4.4 KB
Line 
1/** @file
2 BaseRng Library that uses the TimerLib to provide reasonably random numbers.
3 Do not use this on a production system.
4
5 Copyright (c) Microsoft Corporation.
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7**/
8
9#include <Base.h>
10#include <Library/BaseLib.h>
11#include <Library/DebugLib.h>
12#include <Library/TimerLib.h>
13
14#define DEFAULT_DELAY_TIME_IN_MICROSECONDS 10
15
16/**
17 Using the TimerLib GetPerformanceCounterProperties() we delay
18 for enough time for the PerformanceCounter to increment.
19
20 If the return value from GetPerformanceCounterProperties (TimerLib)
21 is zero, this function will return 10 and attempt to assert.
22 **/
23STATIC
24UINT32
25CalculateMinimumDecentDelayInMicroseconds (
26 VOID
27 )
28{
29 UINT64 CounterHz;
30
31 // Get the counter properties
32 CounterHz = GetPerformanceCounterProperties (NULL, NULL);
33 // Make sure we won't divide by zero
34 if (CounterHz == 0) {
35 ASSERT (CounterHz != 0); // Assert so the developer knows something is wrong
36 return DEFAULT_DELAY_TIME_IN_MICROSECONDS;
37 }
38
39 // Calculate the minimum delay based on 1.5 microseconds divided by the hertz.
40 // We calculate the length of a cycle (1/CounterHz) and multiply it by 1.5 microseconds
41 // This ensures that the performance counter has increased by at least one
42 return (UINT32)(MAX (DivU64x64Remainder (1500000, CounterHz, NULL), 1));
43}
44
45/**
46 Generates a 16-bit random number.
47
48 if Rand is NULL, then ASSERT().
49
50 @param[out] Rand Buffer pointer to store the 16-bit random value.
51
52 @retval TRUE Random number generated successfully.
53 @retval FALSE Failed to generate the random number.
54
55**/
56BOOLEAN
57EFIAPI
58GetRandomNumber16 (
59 OUT UINT16 *Rand
60 )
61{
62 UINT32 Index;
63 UINT8 *RandPtr;
64 UINT32 DelayInMicroSeconds;
65
66 ASSERT (Rand != NULL);
67
68 if (Rand == NULL) {
69 return FALSE;
70 }
71
72 DelayInMicroSeconds = CalculateMinimumDecentDelayInMicroseconds ();
73 RandPtr = (UINT8 *)Rand;
74 // Get 2 bytes of random ish data
75 for (Index = 0; Index < sizeof (UINT16); Index++) {
76 *RandPtr = (UINT8)(GetPerformanceCounter () & 0xFF);
77 // Delay to give the performance counter a chance to change
78 MicroSecondDelay (DelayInMicroSeconds);
79 RandPtr++;
80 }
81
82 return TRUE;
83}
84
85/**
86 Generates a 32-bit random number.
87
88 if Rand is NULL, then ASSERT().
89
90 @param[out] Rand Buffer pointer to store the 32-bit random value.
91
92 @retval TRUE Random number generated successfully.
93 @retval FALSE Failed to generate the random number.
94
95**/
96BOOLEAN
97EFIAPI
98GetRandomNumber32 (
99 OUT UINT32 *Rand
100 )
101{
102 UINT32 Index;
103 UINT8 *RandPtr;
104 UINT32 DelayInMicroSeconds;
105
106 ASSERT (Rand != NULL);
107
108 if (NULL == Rand) {
109 return FALSE;
110 }
111
112 RandPtr = (UINT8 *)Rand;
113 DelayInMicroSeconds = CalculateMinimumDecentDelayInMicroseconds ();
114 // Get 4 bytes of random ish data
115 for (Index = 0; Index < sizeof (UINT32); Index++) {
116 *RandPtr = (UINT8)(GetPerformanceCounter () & 0xFF);
117 // Delay to give the performance counter a chance to change
118 MicroSecondDelay (DelayInMicroSeconds);
119 RandPtr++;
120 }
121
122 return TRUE;
123}
124
125/**
126 Generates a 64-bit random number.
127
128 if Rand is NULL, then ASSERT().
129
130 @param[out] Rand Buffer pointer to store the 64-bit random value.
131
132 @retval TRUE Random number generated successfully.
133 @retval FALSE Failed to generate the random number.
134
135**/
136BOOLEAN
137EFIAPI
138GetRandomNumber64 (
139 OUT UINT64 *Rand
140 )
141{
142 UINT32 Index;
143 UINT8 *RandPtr;
144 UINT32 DelayInMicroSeconds;
145
146 ASSERT (Rand != NULL);
147
148 if (NULL == Rand) {
149 return FALSE;
150 }
151
152 RandPtr = (UINT8 *)Rand;
153 DelayInMicroSeconds = CalculateMinimumDecentDelayInMicroseconds ();
154 // Get 8 bytes of random ish data
155 for (Index = 0; Index < sizeof (UINT64); Index++) {
156 *RandPtr = (UINT8)(GetPerformanceCounter () & 0xFF);
157 // Delay to give the performance counter a chance to change
158 MicroSecondDelay (DelayInMicroSeconds);
159 RandPtr++;
160 }
161
162 return TRUE;
163}
164
165/**
166 Generates a 128-bit random number.
167
168 if Rand is NULL, then ASSERT().
169
170 @param[out] Rand Buffer pointer to store the 128-bit random value.
171
172 @retval TRUE Random number generated successfully.
173 @retval FALSE Failed to generate the random number.
174
175**/
176BOOLEAN
177EFIAPI
178GetRandomNumber128 (
179 OUT UINT64 *Rand
180 )
181{
182 ASSERT (Rand != NULL);
183 // This should take around 80ms
184
185 // Read first 64 bits
186 if (!GetRandomNumber64 (Rand)) {
187 return FALSE;
188 }
189
190 // Read second 64 bits
191 return GetRandomNumber64 (++Rand);
192}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette