VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/BaseRngLibTimerLib/RngLibTimer.c@ 105681

Last change on this file since 105681 was 105670, checked in by vboxsync, 9 months ago

Devices/EFI/FirmwareNew: Merge edk2-stable-202405 and make it build on aarch64, bugref:4643

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