diff options
| author | Michael Brown | 2025-12-11 15:04:10 +0100 |
|---|---|---|
| committer | Michael Brown | 2025-12-12 08:33:55 +0100 |
| commit | 86c40a8b1ef860c7c092226f95f9c8fe2d140edd (patch) | |
| tree | af8397376858013e78bcb48feca73f115701a985 /src/interface/efi | |
| parent | [crypto] Generalise rsa_parse_integer() to asn1_enter_unsigned() (diff) | |
| download | ipxe-86c40a8b1ef860c7c092226f95f9c8fe2d140edd.tar.gz ipxe-86c40a8b1ef860c7c092226f95f9c8fe2d140edd.tar.xz ipxe-86c40a8b1ef860c7c092226f95f9c8fe2d140edd.zip | |
[efi] Retry calls to GetRNG() as needed
The UEFI specification allows GetRNG() to return EFI_NOT_READY, which
is not a particularly helpful error status since there is nothing that
can sensibly be done except to retry immediately.
Retry failed calls to GetRNG() up to a maximum number of attempts.
Debugged-by: Stoo Davies <sdavies@nvidia.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/interface/efi')
| -rw-r--r-- | src/interface/efi/efi_rng.c | 45 |
1 files changed, 30 insertions, 15 deletions
diff --git a/src/interface/efi/efi_rng.c b/src/interface/efi/efi_rng.c index b76a6fc0d..058f0ee7d 100644 --- a/src/interface/efi/efi_rng.c +++ b/src/interface/efi/efi_rng.c @@ -54,6 +54,15 @@ EFI_REQUEST_PROTOCOL ( EFI_RNG_PROTOCOL, &efirng ); */ #define EFIRNG_LEN 32 +/** Maximum number of times to attempting requesting data from RNG + * + * The UEFI spec allows GetRNG() to return EFI_NOT_READY, which is not + * a particularly helpful error status since there is nothing that can + * sensibly be done except to retry immediately. We retry failed + * calls to GetRNG() (for any reason) up to this number of times. + */ +#define EFIRNG_MAX_RETRY 16 + /** * Enable entropy gathering * @@ -85,29 +94,35 @@ static int efirng_enable ( void ) { */ static int efirng_get_noise ( noise_sample_t *noise ) { uint8_t buf[EFIRNG_LEN]; + unsigned int i; EFI_STATUS efirc; int rc; /* Sanity check */ assert ( efirng != NULL ); - /* Get the minimum allowed number of random bytes */ - if ( ( efirc = efirng->GetRNG ( efirng, NULL, sizeof ( buf ), - buf ) ) != 0 ) { - rc = -EEFI ( efirc ); - DBGC ( &efirng, "ENTROPY could not read from RNG: %s\n", - strerror ( rc ) ); - return rc; + /* Get random bytes, retrying if needed */ + for ( i = 0 ; i < EFIRNG_MAX_RETRY ; i++ ) { + + /* Get the minimum allowed number of random bytes */ + if ( ( efirc = efirng->GetRNG ( efirng, NULL, sizeof ( buf ), + buf ) ) != 0 ) { + rc = -EEFI ( efirc ); + continue; + } + + /* 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; } - /* 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; + DBGC ( &efirng, "ENTROPY could not read from RNG: %s\n", + strerror ( rc ) ); + return rc; } /** EFI random number generator protocol entropy source */ |
