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.
This commit is contained in:
+45
-25
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user