TianoCore EDK2 master
Loading...
Searching...
No Matches
Rng.c
Go to the documentation of this file.
1
10#include <Uefi.h>
11#include <Library/BaseLib.h>
12#include <Library/DebugLib.h>
13#include <Library/RngLib.h>
15
16#include "BaseRngLibInternals.h"
17#define RISCV_CPU_FEATURE_ZKR_BITMASK 0x8
18
19#define SEED_RETRY_LOOPS 100
20
21// 64-bit Mersenne Twister implementation
22// A widely used pseudo random number generator. It performs bit shifts etc to
23// achieve the random number. It's output is determined by SEED value generated
24// by RISC-V SEED CSR"
25
26#define STATE_SIZE 312
27#define MIDDLE 156
28#define INIT_SHIFT 62
29#define TWIST_MASK 0xb5026f5aa96619e9ULL
30#define INIT_FACT 6364136223846793005ULL
31#define SHIFT1 29
32#define MASK1 0x5555555555555555ULL
33#define SHIFT2 17
34#define MASK2 0x71d67fffeda60000ULL
35#define SHIFT3 37
36#define MASK3 0xfff7eee000000000ULL
37#define SHIFT4 43
38
39#define LOWER_MASK 0x7fffffff
40#define UPPER_MASK (~(UINT64)LOWER_MASK)
41
42static UINT64 mState[STATE_SIZE];
43static UINTN mIndex = STATE_SIZE + 1;
44
51VOID
53 IN UINT64 S
54 )
55{
56 UINTN I;
57
58 mIndex = STATE_SIZE;
59 mState[0] = S;
60
61 for (I = 1; I < STATE_SIZE; I++) {
62 mState[I] = (INIT_FACT * (mState[I - 1] ^ (mState[I - 1] >> INIT_SHIFT))) + I;
63 }
64}
65
74VOID
76 VOID
77 )
78{
79 UINTN I;
80 UINT64 X;
81
82 for (I = 0; I < STATE_SIZE; I++) {
83 X = (mState[I] & UPPER_MASK) | (mState[(I + 1) % STATE_SIZE] & LOWER_MASK);
84 X = (X >> 1) ^ (X & 1 ? TWIST_MASK : 0);
85 mState[I] = mState[(I + MIDDLE) % STATE_SIZE] ^ X;
86 }
87
88 mIndex = 0;
89}
90
91// Defined in Seed.S
92extern UINT64
93ReadSeed (
94 VOID
95 );
96
105STATIC
106BOOLEAN
108 OUT UINT64 *Out
109 )
110{
111 UINT64 Seed;
112 UINTN Retry;
113 UINTN ValidSeeds;
114 UINTN NeededSeeds;
115 UINT16 *Entropy;
116
117 Retry = SEED_RETRY_LOOPS;
118 Entropy = (UINT16 *)Out;
119 NeededSeeds = sizeof (UINT64) / sizeof (UINT16);
120 ValidSeeds = 0;
121
122 if (!ArchIsRngSupported ()) {
123 DEBUG ((DEBUG_ERROR, "Get64BitSeed: HW not supported!\n"));
124 return FALSE;
125 }
126
127 do {
128 Seed = ReadSeed ();
129
130 switch (Seed & SEED_OPST_MASK) {
131 case SEED_OPST_ES16:
132 Entropy[ValidSeeds++] = Seed & SEED_ENTROPY_MASK;
133 if (ValidSeeds == NeededSeeds) {
134 return TRUE;
135 }
136
137 break;
138
139 case SEED_OPST_DEAD:
140 DEBUG ((DEBUG_ERROR, "Get64BitSeed: Unrecoverable error!\n"));
141 return FALSE;
142
143 case SEED_OPST_BIST: // fallthrough
144 case SEED_OPST_WAIT: // fallthrough
145 default:
146 continue;
147 }
148 } while (--Retry);
149
150 return FALSE;
151}
152
161EFIAPI
163 VOID
164 )
165{
166 UINT64 Seed;
167
168 if (Get64BitSeed (&Seed)) {
169 SeedRng (Seed);
170 return EFI_SUCCESS;
171 } else {
172 return EFI_UNSUPPORTED;
173 }
174}
175
185BOOLEAN
186EFIAPI
188 OUT UINT16 *Rand
189 )
190{
191 UINT64 Rand64;
192
193 if (ArchGetRandomNumber64 (&Rand64)) {
194 *Rand = Rand64 & MAX_UINT16;
195 return TRUE;
196 }
197
198 return FALSE;
199}
200
210BOOLEAN
211EFIAPI
213 OUT UINT32 *Rand
214 )
215{
216 UINT64 Rand64;
217
218 if (ArchGetRandomNumber64 (&Rand64)) {
219 *Rand = Rand64 & MAX_UINT32;
220 return TRUE;
221 }
222
223 return FALSE;
224}
225
235BOOLEAN
236EFIAPI
238 OUT UINT64 *Rand
239 )
240{
241 UINT64 Y;
242
243 // Never initialized.
244 if (mIndex > STATE_SIZE) {
245 return FALSE;
246 }
247
248 // Mersenne Twister
249 if (mIndex == STATE_SIZE) {
250 TwistRng ();
251 }
252
253 Y = mState[mIndex];
254 Y ^= (Y >> SHIFT1) & MASK1;
255 Y ^= (Y << SHIFT2) & MASK2;
256 Y ^= (Y << SHIFT3) & MASK3;
257 Y ^= Y >> SHIFT4;
258
259 mIndex++;
260
261 *Rand = Y;
262 return TRUE;
263}
264
270BOOLEAN
271EFIAPI
273 VOID
274 )
275{
276 return ((PcdGet64 (PcdRiscVFeatureOverride) & RISCV_CPU_FEATURE_ZKR_BITMASK) != 0);
277}
UINT64 UINTN
#define STATIC
Definition: Base.h:264
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define PcdGet64(TokenName)
Definition: PcdLib.h:375
BOOLEAN EFIAPI ArchGetRandomNumber16(OUT UINT16 *Rand)
Definition: Rng.c:187
EFI_STATUS EFIAPI BaseRngLibConstructor(VOID)
Definition: Rng.c:162
BOOLEAN EFIAPI ArchGetRandomNumber64(OUT UINT64 *Rand)
Definition: Rng.c:237
BOOLEAN EFIAPI ArchGetRandomNumber32(OUT UINT32 *Rand)
Definition: Rng.c:212
STATIC BOOLEAN Get64BitSeed(OUT UINT64 *Out)
Definition: Rng.c:107
BOOLEAN EFIAPI ArchIsRngSupported(VOID)
Definition: Rng.c:272
STATIC VOID TwistRng(VOID)
Definition: Rng.c:75
STATIC VOID SeedRng(IN UINT64 S)
Definition: Rng.c:52
UINTN Rand(VOID)
Definition: Support.c:39
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112