From 6dc6b48ec98ad6eccd5af00b4c96bb70cff9286c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 7 Mar 2026 22:11:44 +0100 Subject: [PATCH] random-seed: when we have a reasonable RNG then create random seed file if missing Previously we'd never write the ESP random seed file (or initialize the random seed EFI table) if it didn't already exist. Let's adjust this a bit, and also create it fresh if we have a "good" random source, i.e. if the EFI table already existed or if the RNG protocol is implemented by EFI. This is useful as it increases the chance the random seed table is valid, and we can use it as source for randomness in later stages. --- src/boot/random-seed.c | 70 +++++++++++++++++++++++++++--------------- 1 file changed, 45 insertions(+), 25 deletions(-) diff --git a/src/boot/random-seed.c b/src/boot/random-seed.c index 8ef7ee7e52..a31215c3b0 100644 --- a/src/boot/random-seed.c +++ b/src/boot/random-seed.c @@ -185,46 +185,66 @@ EFI_STATUS process_random_seed(EFI_FILE *root_dir) { explicit_bzero_safe(system_token, size); } + bool created = false; err = root_dir->Open( root_dir, &handle, (char16_t *) u"\\loader\\random-seed", EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE, 0); + if (err == EFI_NOT_FOUND && seeded_by_efi) { + /* If the file does not exist, but we are reasonably well seeded, create the seed file */ + created = true; + err = root_dir->Open( + root_dir, + &handle, + (char16_t *) u"\\loader\\random-seed", + EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, + 0); + } if (err != EFI_SUCCESS) { if (!IN_SET(err, EFI_NOT_FOUND, EFI_WRITE_PROTECTED)) log_error_status(err, "Failed to open random seed file: %m"); return err; } - err = get_file_info(handle, &info, NULL); - if (err != EFI_SUCCESS) - return log_error_status(err, "Failed to get file info for random seed: %m"); + if (!created) { + err = get_file_info(handle, &info, /* ret_size= */ NULL); + if (err != EFI_SUCCESS) + return log_error_status(err, "Failed to get file info for random seed: %m"); - size = info->FileSize; - if (size < RANDOM_MAX_SIZE_MIN) - return log_error_status(EFI_INVALID_PARAMETER, "Random seed file is too short."); - - if (size > RANDOM_MAX_SIZE_MAX) - return log_error_status(EFI_INVALID_PARAMETER, "Random seed file is too large."); - - seed = xmalloc(size); - rsize = size; - err = handle->Read(handle, &rsize, seed); - if (err != EFI_SUCCESS) - return log_error_status(err, "Failed to read random seed file: %m"); - if (rsize != size) { - explicit_bzero_safe(seed, rsize); - return log_error_status(EFI_PROTOCOL_ERROR, "Short read on random seed file."); + /* Treat a short file just like a freshly created one for robustness reasons: consider a case + * where in a previous run a file was just created and the system was then powered off. In + * such a case the file will already exist, but be too short. */ + created = info->FileSize < RANDOM_MAX_SIZE_MIN; } - sha256_process_bytes(&size, sizeof(size), &hash); - sha256_process_bytes(seed, size, &hash); - explicit_bzero_safe(seed, size); + if (created) { + size = 0; + sha256_process_bytes(&size, sizeof(size), &hash); + } else { + size = info->FileSize; + if (size > RANDOM_MAX_SIZE_MAX) + return log_error_status(EFI_INVALID_PARAMETER, "Random seed file is too large."); - err = handle->SetPosition(handle, 0); - if (err != EFI_SUCCESS) - return log_error_status(err, "Failed to seek to beginning of random seed file: %m"); + seed = xmalloc(size); + rsize = size; + err = handle->Read(handle, &rsize, seed); + if (err != EFI_SUCCESS) + return log_error_status(err, "Failed to read random seed file: %m"); + if (rsize != size) { + explicit_bzero_safe(seed, rsize); + return log_error_status(EFI_PROTOCOL_ERROR, "Short read on random seed file."); + } + + sha256_process_bytes(&size, sizeof(size), &hash); + sha256_process_bytes(seed, size, &hash); + explicit_bzero_safe(seed, size); + + err = handle->SetPosition(handle, 0); + if (err != EFI_SUCCESS) + return log_error_status(err, "Failed to seek to beginning of random seed file: %m"); + } /* Let's also include the UEFI monotonic counter (which is supposedly increasing on every single * boot) in the hash, so that even if the changes to the ESP for some reason should not be @@ -253,7 +273,7 @@ EFI_STATUS process_random_seed(EFI_FILE *root_dir) { size = sizeof(random_bytes); /* If the file size is too large, zero out the remaining bytes on disk. */ - if (size < info->FileSize) { + if (!created && size < info->FileSize) { err = handle->SetPosition(handle, size); if (err != EFI_SUCCESS) return log_error_status(err, "Failed to seek to offset of random seed file: %m");