aboutsummaryrefslogtreecommitdiffstats
path: root/src/interface/efi/efi_entropy.c
diff options
context:
space:
mode:
authorMichael Brown <mcb30@ipxe.org>2020-06-28 19:24:30 +0100
committerMichael Brown <mcb30@ipxe.org>2020-06-28 19:58:48 +0100
commita87537d44c4fc46a41620af4591616057a89bf95 (patch)
treebcc2753d5fac5e866799c1b1322ebe003fb4b2df /src/interface/efi/efi_entropy.c
parentdecee20ec84977ae1d1a7f54fa91e73017f6731d (diff)
downloadipxe-a87537d44c4fc46a41620af4591616057a89bf95.tar.gz
[efi] Detect and disable seriously broken EFI_RNG_PROTOCOL implementations
The EFI_RNG_PROTOCOL on the Microsoft Surface Go does not generate random numbers. Successive calls to GetRNG() without any intervening I/O operations (such as writing to the console) will produce identical results. Successive reboots will produce identical results. It is unclear what the Microsoft Surface Go is attempting to use as an entropy source, but it is demonstrably producing zero bits of entropy. The failure is already detected by the ANS-mandated Repetition Count Test performed as part of our GetEntropy implementation. This currently results in the entropy source being marked as broken, with the result that iPXE refuses to perform any operations that require a working entropy source. We cannot use the existing EFI driver blacklisting mechanism to unload the broken driver, since the RngDxe driver is integrated into the DxeCore image. Work around the broken driver by checking for consecutive identical results returned by EFI_RNG_PROTOCOL and falling back to the original timer-based entropy source. Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/interface/efi/efi_entropy.c')
-rw-r--r--src/interface/efi/efi_entropy.c12
1 files changed, 12 insertions, 0 deletions
diff --git a/src/interface/efi/efi_entropy.c b/src/interface/efi/efi_entropy.c
index 2a2fc9054..dca0b6f1d 100644
--- a/src/interface/efi/efi_entropy.c
+++ b/src/interface/efi/efi_entropy.c
@@ -179,6 +179,7 @@ static int efi_get_noise_ticks ( noise_sample_t *noise ) {
* @ret rc Return status code
*/
static int efi_get_noise_rng ( noise_sample_t *noise ) {
+ static uint8_t prev[EFI_ENTROPY_RNG_LEN];
uint8_t buf[EFI_ENTROPY_RNG_LEN];
EFI_STATUS efirc;
int rc;
@@ -196,6 +197,17 @@ static int efi_get_noise_rng ( noise_sample_t *noise ) {
return rc;
}
+ /* Fail (and permanently disable the EFI RNG) if we get
+ * consecutive identical results.
+ */
+ if ( memcmp ( buf, prev, sizeof ( buf ) ) == 0 ) {
+ DBGC ( &tick, "ENTROPY detected broken EFI RNG:\n" );
+ DBGC_HDA ( &tick, 0, buf, sizeof ( buf ) );
+ efirng = NULL;
+ return -EIO;
+ }
+ memcpy ( prev, buf, sizeof ( prev ) );
+
/* Reduce random bytes to a single noise sample. This seems
* like overkill, but we have no way of knowing how much
* entropy is actually present in the bytes returned by the