mirror of
https://github.com/ipxe/ipxe
synced 2025-12-25 09:01:24 +03:00
[rng] Allow entropy source to be selected at runtime
As noted in commit3c83843("[rng] Check for several functioning RTC interrupts"), experimentation shows that Hyper-V cannot be trusted to reliably generate RTC interrupts. (As noted in commitf3ba0fb("[hyperv] Provide timer based on the 10MHz time reference count MSR"), Hyper-V appears to suffer from a general problem in reliably generating any legacy interrupts.) An alternative entropy source is therefore required for an image that may be used in a Hyper-V Gen1 virtual machine. The x86 RDRAND instruction provides a suitable alternative entropy source, but may not be supported by all CPUs. We must therefore allow for multiple entropy sources to be compiled in, with the single active entropy source selected only at runtime. Restructure the internal entropy API to allow a working entropy source to be detected and chosen at runtime. Enable the RDRAND entropy source for all x86 builds, since it is likely to be substantially faster than any other source. Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
@@ -36,6 +36,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
*
|
||||
*/
|
||||
|
||||
struct entropy_source efi_entropy __entropy_source ( ENTROPY_NORMAL );
|
||||
|
||||
/** Random number generator protocol */
|
||||
static EFI_RNG_PROTOCOL *efirng;
|
||||
EFI_REQUEST_PROTOCOL ( EFI_RNG_PROTOCOL, &efirng );
|
||||
@@ -91,6 +93,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 ( &efi_entropy, MIN_ENTROPY ( 1.3 ) );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -235,7 +243,10 @@ static int efi_get_noise ( noise_sample_t *noise ) {
|
||||
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 efi_entropy __entropy_source ( ENTROPY_NORMAL ) = {
|
||||
.name = "efi",
|
||||
.enable = efi_entropy_enable,
|
||||
.disable = efi_entropy_disable,
|
||||
.get_noise = efi_get_noise,
|
||||
};
|
||||
|
||||
@@ -34,6 +34,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
#include <ipxe/linux_api.h>
|
||||
#include <ipxe/entropy.h>
|
||||
|
||||
struct entropy_source linux_entropy __entropy_source ( ENTROPY_NORMAL );
|
||||
|
||||
/** Entropy source filename */
|
||||
static const char entropy_filename[] = "/dev/random";
|
||||
|
||||
@@ -55,6 +57,13 @@ static int linux_entropy_enable ( void ) {
|
||||
return entropy_fd;
|
||||
}
|
||||
|
||||
/* linux_get_noise() reads a single byte from /dev/random,
|
||||
* which is supposed to block until a sufficient amount of
|
||||
* entropy is available. We therefore assume that each sample
|
||||
* contains exactly 8 bits of entropy.
|
||||
*/
|
||||
entropy_init ( &linux_entropy, MIN_ENTROPY ( 8.0 ) );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -95,7 +104,10 @@ static int linux_get_noise ( noise_sample_t *noise ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
PROVIDE_ENTROPY_INLINE ( linux, min_entropy_per_sample );
|
||||
PROVIDE_ENTROPY ( linux, entropy_enable, linux_entropy_enable );
|
||||
PROVIDE_ENTROPY ( linux, entropy_disable, linux_entropy_disable );
|
||||
PROVIDE_ENTROPY ( linux, get_noise, linux_get_noise );
|
||||
/** Linux entropy source */
|
||||
struct entropy_source linux_entropy __entropy_source ( ENTROPY_NORMAL ) = {
|
||||
.name = "linux",
|
||||
.enable = linux_entropy_enable,
|
||||
.disable = linux_entropy_disable,
|
||||
.get_noise = linux_get_noise,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user