diff options
| author | Simon Rettberg | 2023-04-04 15:12:41 +0200 |
|---|---|---|
| committer | Simon Rettberg | 2023-04-04 15:12:41 +0200 |
| commit | 5ba496dce11d10198a0eae0c8440dccb256fbf32 (patch) | |
| tree | 549903f1dab893870335a6e4767a4530444d2e83 /src/interface/efi/efi_entropy.c | |
| parent | [vesafb] Map Unicode characters to CP437 if possible (diff) | |
| parent | [tls] Handle fragmented handshake records (diff) | |
| download | ipxe-5ba496dce11d10198a0eae0c8440dccb256fbf32.tar.gz ipxe-5ba496dce11d10198a0eae0c8440dccb256fbf32.tar.xz ipxe-5ba496dce11d10198a0eae0c8440dccb256fbf32.zip | |
Merge branch 'master' into openslx
Diffstat (limited to 'src/interface/efi/efi_entropy.c')
| -rw-r--r-- | src/interface/efi/efi_entropy.c | 109 |
1 files changed, 19 insertions, 90 deletions
diff --git a/src/interface/efi/efi_entropy.c b/src/interface/efi/efi_entropy.c index 71341d9d4..8e55c77b1 100644 --- a/src/interface/efi/efi_entropy.c +++ b/src/interface/efi/efi_entropy.c @@ -25,10 +25,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include <errno.h> #include <ipxe/entropy.h> -#include <ipxe/crc32.h> #include <ipxe/profile.h> #include <ipxe/efi/efi.h> -#include <ipxe/efi/Protocol/Rng.h> #if defined(__i386) || defined(__x86_64) #include <ipxe/cpuid.h> @@ -41,22 +39,7 @@ static char have_hwrnd = 0; * */ -/** Random number generator protocol */ -static EFI_RNG_PROTOCOL *efirng; -EFI_REQUEST_PROTOCOL ( EFI_RNG_PROTOCOL, &efirng ); - -/** Minimum number of bytes to request from RNG - * - * The UEFI spec states (for no apparently good reason) that "When a - * Deterministic Random Bit Generator (DRBG) is used on the output of - * a (raw) entropy source, its security level must be at least 256 - * bits." The EDK2 codebase (mis)interprets this to mean that the - * call to GetRNG() should fail if given a buffer less than 32 bytes. - * - * Incidentally, nothing in the EFI RNG protocol provides any way to - * report the actual amount of entropy returned by GetRNG(). - */ -#define EFI_ENTROPY_RNG_LEN 32 +struct entropy_source efitick_entropy __entropy_source ( ENTROPY_FALLBACK ); /** Time (in 100ns units) to delay waiting for timer tick * @@ -81,9 +64,6 @@ static int efi_entropy_enable ( void ) { EFI_STATUS efirc; int rc; - DBGC ( &tick, "ENTROPY %s RNG protocol\n", - ( efirng ? "has" : "has no" ) ); - /* Drop to external TPL to allow timer tick event to take place */ bs->RestoreTPL ( efi_external_tpl ); @@ -96,6 +76,12 @@ static int efi_entropy_enable ( void ) { return rc; } + /* We use essentially the same mechanism as for the BIOS + * RTC-based entropy source, and so assume the same + * min-entropy per sample. + */ + entropy_init ( &efitick_entropy, MIN_ENTROPY ( 1.3 ) ); + return 0; } @@ -190,11 +176,15 @@ static int efi_get_noise_rdrand ( noise_sample_t *noise ) { * @ret noise Noise sample * @ret rc Return status code */ -static int efi_get_noise_ticks ( noise_sample_t *noise ) { +static int efi_get_noise ( noise_sample_t *noise ) { int before; int after; int rc; + rc = efi_get_noise_rdrand ( noise ); + if ( rc == 0 ) + return 0; + /* Wait for a timer tick */ before = efi_entropy_tick(); if ( before < 0 ) { @@ -215,71 +205,10 @@ static int efi_get_noise_ticks ( noise_sample_t *noise ) { return 0; } -/** - * Get noise sample from RNG protocol - * - * @ret noise Noise sample - * @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; - - /* Fail if we have no EFI RNG protocol */ - if ( ! efirng ) - return -ENOTSUP; - - /* Get the minimum allowed number of random bytes */ - if ( ( efirc = efirng->GetRNG ( efirng, NULL, EFI_ENTROPY_RNG_LEN, - buf ) ) != 0 ) { - rc = -EEFI ( efirc ); - DBGC ( &tick, "ENTROPY could not read from RNG: %s\n", - strerror ( rc ) ); - 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 - * RNG protocol. - */ - *noise = crc32_le ( 0, buf, sizeof ( buf ) ); - - return 0; -} - -/** - * Get noise sample - * - * @ret noise Noise sample - * @ret rc Return status code - */ -static int efi_get_noise ( noise_sample_t *noise ) { - int rc; - - /* Try RNG first, falling back to timer ticks */ - if ( ( ( rc = efi_get_noise_rng ( noise ) ) != 0 ) && - ( ( rc = efi_get_noise_rdrand ( noise ) ) != 0 ) && - ( ( rc = efi_get_noise_ticks ( noise ) ) != 0 ) ) - return rc; - - return 0; -} - -PROVIDE_ENTROPY_INLINE ( efi, min_entropy_per_sample ); -PROVIDE_ENTROPY ( efi, entropy_enable, efi_entropy_enable ); -PROVIDE_ENTROPY ( efi, entropy_disable, efi_entropy_disable ); -PROVIDE_ENTROPY ( efi, get_noise, efi_get_noise ); +/** EFI entropy source */ +struct entropy_source efitick_entropy __entropy_source ( ENTROPY_FALLBACK ) = { + .name = "efitick", + .enable = efi_entropy_enable, + .disable = efi_entropy_disable, + .get_noise = efi_get_noise, +}; |
