Changeset 108794 in vbox for trunk/src/VBox/Devices/EFI/FirmwareNew/MdePkg/Library/BaseRngLib/Rand/RdRand.c
- Timestamp:
- Mar 31, 2025 11:31:09 AM (2 weeks ago)
- svn:sync-xref-src-repo-rev:
- 168237
- Location:
- trunk/src/VBox/Devices/EFI/FirmwareNew
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/EFI/FirmwareNew
-
Property svn:mergeinfo
changed from (toggle deleted branches)
to (toggle deleted branches)/vendor/edk2/current 103735-103757,103769-103776,129194-164365 /vendor/edk2/current 103735-103757,103769-103776,129194-168232
-
Property svn:mergeinfo
changed from (toggle deleted branches)
-
trunk/src/VBox/Devices/EFI/FirmwareNew/MdePkg/Library/BaseRngLib/Rand/RdRand.c
r105670 r108794 3 3 to provide high-quality random numbers. 4 4 5 Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR> 5 6 Copyright (c) 2023, Arm Limited. All rights reserved.<BR> 7 Copyright (c) 2022, Pedro Falcato. All rights reserved.<BR> 6 8 Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR> 7 9 Copyright (c) 2015, Intel Corporation. All rights reserved.<BR> … … 23 25 #define RDRAND_MASK BIT30 24 26 25 STATIC BOOLEAN mRdRandSupported; 27 // 28 // Intel SDM says 10 tries is good enough for reliable RDRAND usage. 29 // 30 #define RDRAND_RETRIES 10 31 32 #define RDRAND_TEST_SAMPLES 8 33 34 #define RDRAND_MIN_CHANGE 5 35 36 // 37 // Add a define for native-word RDRAND, just for the test. 38 // 39 #ifdef MDE_CPU_X64 40 #define ASM_RDRAND AsmRdRand64 41 #else 42 #define ASM_RDRAND AsmRdRand32 43 #endif 44 45 /** 46 Tests RDRAND for broken implementations. 47 48 @retval TRUE RDRAND is reliable (and hopefully safe). 49 @retval FALSE RDRAND is unreliable and should be disabled, despite CPUID. 50 51 **/ 52 STATIC 53 BOOLEAN 54 TestRdRand ( 55 VOID 56 ) 57 { 58 // 59 // Test for notoriously broken rdrand implementations that always return the same 60 // value, like the Zen 3 uarch (all-1s) or other several AMD families on suspend/resume (also all-1s). 61 // Note that this should be expanded to extensively test for other sorts of possible errata. 62 // 63 64 // 65 // Our algorithm samples rdrand $RDRAND_TEST_SAMPLES times and expects 66 // a different result $RDRAND_MIN_CHANGE times for reliable RDRAND usage. 67 // 68 UINTN Prev; 69 UINT8 Idx; 70 UINT8 TestIteration; 71 UINT32 Changed; 72 73 Changed = 0; 74 75 for (TestIteration = 0; TestIteration < RDRAND_TEST_SAMPLES; TestIteration++) { 76 UINTN Sample; 77 // 78 // Note: We use a retry loop for rdrand. Normal users get this in BaseRng.c 79 // Any failure to get a random number will assume RDRAND does not work. 80 // 81 for (Idx = 0; Idx < RDRAND_RETRIES; Idx++) { 82 if (ASM_RDRAND (&Sample)) { 83 break; 84 } 85 } 86 87 if (Idx == RDRAND_RETRIES) { 88 DEBUG ((DEBUG_ERROR, "BaseRngLib/x86: CPU BUG: Failed to get an RDRAND random number - disabling\n")); 89 return FALSE; 90 } 91 92 if (TestIteration != 0) { 93 Changed += Sample != Prev; 94 } 95 96 Prev = Sample; 97 } 98 99 if (Changed < RDRAND_MIN_CHANGE) { 100 DEBUG ((DEBUG_ERROR, "BaseRngLib/x86: CPU BUG: RDRAND not reliable - disabling\n")); 101 return FALSE; 102 } 103 104 return TRUE; 105 } 106 107 #undef ASM_RDRAND 26 108 27 109 /** … … 42 124 ) 43 125 { 44 UINT32 RegEcx; 126 return EFI_SUCCESS; 127 } 128 129 /** 130 Generates a 16-bit random number. 131 132 @param[out] Rand Buffer pointer to store the 16-bit random value. 133 134 @retval TRUE Random number generated successfully. 135 @retval FALSE Failed to generate the random number. 136 137 **/ 138 BOOLEAN 139 EFIAPI 140 ArchGetRandomNumber16 ( 141 OUT UINT16 *Rand 142 ) 143 { 144 return AsmRdRand16 (Rand); 145 } 146 147 /** 148 Generates a 32-bit random number. 149 150 @param[out] Rand Buffer pointer to store the 32-bit random value. 151 152 @retval TRUE Random number generated successfully. 153 @retval FALSE Failed to generate the random number. 154 155 **/ 156 BOOLEAN 157 EFIAPI 158 ArchGetRandomNumber32 ( 159 OUT UINT32 *Rand 160 ) 161 { 162 return AsmRdRand32 (Rand); 163 } 164 165 /** 166 Generates a 64-bit random number. 167 168 @param[out] Rand Buffer pointer to store the 64-bit random value. 169 170 @retval TRUE Random number generated successfully. 171 @retval FALSE Failed to generate the random number. 172 173 **/ 174 BOOLEAN 175 EFIAPI 176 ArchGetRandomNumber64 ( 177 OUT UINT64 *Rand 178 ) 179 { 180 return AsmRdRand64 (Rand); 181 } 182 183 /** 184 Checks whether RDRAND is supported. 185 186 @retval TRUE RDRAND is supported. 187 @retval FALSE RDRAND is not supported. 188 189 **/ 190 BOOLEAN 191 EFIAPI 192 ArchIsRngSupported ( 193 VOID 194 ) 195 { 196 BOOLEAN RdRandSupported; 197 UINT32 RegEcx; 45 198 46 199 // … … 49 202 // 50 203 AsmCpuid (1, 0, 0, &RegEcx, 0); 51 ASSERT ((RegEcx & RDRAND_MASK) == RDRAND_MASK); 52 53 mRdRandSupported = ((RegEcx & RDRAND_MASK) == RDRAND_MASK); 54 55 return EFI_SUCCESS; 56 } 57 58 /** 59 Generates a 16-bit random number. 60 61 @param[out] Rand Buffer pointer to store the 16-bit random value. 62 63 @retval TRUE Random number generated successfully. 64 @retval FALSE Failed to generate the random number. 65 66 **/ 67 BOOLEAN 68 EFIAPI 69 ArchGetRandomNumber16 ( 70 OUT UINT16 *Rand 71 ) 72 { 73 return AsmRdRand16 (Rand); 74 } 75 76 /** 77 Generates a 32-bit random number. 78 79 @param[out] Rand Buffer pointer to store the 32-bit random value. 80 81 @retval TRUE Random number generated successfully. 82 @retval FALSE Failed to generate the random number. 83 84 **/ 85 BOOLEAN 86 EFIAPI 87 ArchGetRandomNumber32 ( 88 OUT UINT32 *Rand 89 ) 90 { 91 return AsmRdRand32 (Rand); 92 } 93 94 /** 95 Generates a 64-bit random number. 96 97 @param[out] Rand Buffer pointer to store the 64-bit random value. 98 99 @retval TRUE Random number generated successfully. 100 @retval FALSE Failed to generate the random number. 101 102 **/ 103 BOOLEAN 104 EFIAPI 105 ArchGetRandomNumber64 ( 106 OUT UINT64 *Rand 107 ) 108 { 109 return AsmRdRand64 (Rand); 110 } 111 112 /** 113 Checks whether RDRAND is supported. 114 115 @retval TRUE RDRAND is supported. 116 @retval FALSE RDRAND is not supported. 117 118 **/ 119 BOOLEAN 120 EFIAPI 121 ArchIsRngSupported ( 122 VOID 123 ) 124 { 125 /* 126 Existing software depends on this always returning TRUE, so for 127 now hard-code it. 128 129 return mRdRandSupported; 130 */ 131 return TRUE; 204 205 RdRandSupported = ((RegEcx & RDRAND_MASK) == RDRAND_MASK); 206 207 if (RdRandSupported) { 208 RdRandSupported = TestRdRand (); 209 } 210 211 return RdRandSupported; 132 212 } 133 213
Note:
See TracChangeset
for help on using the changeset viewer.