diff --git a/TODO b/TODO index 2ae9aae7e2..9ff2a90fd4 100644 --- a/TODO +++ b/TODO @@ -263,10 +263,6 @@ Features: * sd-boot: rework random seed handling following recent kernel changes: always pass seed to kernel, but credit only if secure boot is used -* sd-boot: hash data from GetNextHighMonotonicCount() into updated random seed, - so that we might even open up up the random seed logic to non-SecureBoot - systems? - * sd-boot: also include the hyperv "vm generation id" in the random seed hash, to cover nicely for machine clones. It's found in the ACPI tables, which should be easily accessible from UEFI. diff --git a/src/boot/efi/random-seed.c b/src/boot/efi/random-seed.c index b007f41f7e..b01e232f63 100644 --- a/src/boot/efi/random-seed.c +++ b/src/boot/efi/random-seed.c @@ -48,6 +48,7 @@ static void hash_once( UINTN size, const void *system_token, UINTN system_token_size, + UINT64 uefi_monotonic_counter, UINTN counter, UINT8 ret[static HASH_VALUE_SIZE]) { @@ -56,7 +57,8 @@ static void hash_once( * 1. The contents of the old seed file * 2. Some random data acquired from the UEFI RNG (optional) * 3. Some 'system token' the installer installed as EFI variable (optional) - * 4. A counter value + * 4. The UEFI "monotonic counter" that increases with each boot + * 5. A supplied counter value * * And writes the result to the specified buffer. */ @@ -72,6 +74,7 @@ static void hash_once( sha256_process_bytes(rng, size, &hash); if (system_token_size > 0) sha256_process_bytes(system_token, system_token_size, &hash); + sha256_process_bytes(&uefi_monotonic_counter, sizeof(uefi_monotonic_counter), &hash); sha256_process_bytes(&counter, sizeof(counter), &hash); sha256_finish_ctx(&hash, ret); } @@ -82,6 +85,7 @@ static EFI_STATUS hash_many( UINTN size, const void *system_token, UINTN system_token_size, + UINT64 uefi_monotonic_counter, UINTN counter_start, UINTN n, void **ret) { @@ -100,6 +104,7 @@ static EFI_STATUS hash_many( for (UINTN i = 0; i < n; i++) hash_once(old_seed, rng, size, system_token, system_token_size, + uefi_monotonic_counter, counter_start + i, (UINT8*) output + (i * HASH_VALUE_SIZE)); @@ -113,6 +118,7 @@ static EFI_STATUS mangle_random_seed( UINTN size, const void *system_token, UINTN system_token_size, + UINT64 uefi_monotonic_counter, void **ret_new_seed, void **ret_for_kernel) { @@ -134,12 +140,12 @@ static EFI_STATUS mangle_random_seed( n = (size + HASH_VALUE_SIZE - 1) / HASH_VALUE_SIZE; /* Begin hashing in counter mode at counter 0 for the new seed for the disk */ - err = hash_many(old_seed, rng, size, system_token, system_token_size, 0, n, &new_seed); + err = hash_many(old_seed, rng, size, system_token, system_token_size, uefi_monotonic_counter, 0, n, &new_seed); if (EFI_ERROR(err)) return err; /* Continue counting at 'n' for the seed for the kernel */ - err = hash_many(old_seed, rng, size, system_token, system_token_size, n, n, &for_kernel); + err = hash_many(old_seed, rng, size, system_token, system_token_size, uefi_monotonic_counter, n, n, &for_kernel); if (EFI_ERROR(err)) return err; @@ -228,6 +234,7 @@ EFI_STATUS process_random_seed(EFI_FILE *root_dir, RandomSeedMode mode) { _cleanup_(file_closep) EFI_FILE *handle = NULL; UINTN size, rsize, wsize, system_token_size = 0; _cleanup_freepool_ EFI_FILE_INFO *info = NULL; + UINT64 uefi_monotonic_counter = 0; EFI_STATUS err; assert(root_dir); @@ -285,8 +292,15 @@ EFI_STATUS process_random_seed(EFI_FILE *root_dir, RandomSeedMode mode) { * golden master images that are replicated many times. */ (void) acquire_rng(size, &rng); /* It's fine if this fails */ + /* 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 + * persistent, the random seed we generate will still be different on every single boot. */ + err = BS->GetNextMonotonicCount(&uefi_monotonic_counter); + if (EFI_ERROR(err)) + return log_error_status_stall(err, L"Failed to acquire UEFI monotonic counter: %r", err); + /* Calculate new random seed for the disk and what to pass to the kernel */ - err = mangle_random_seed(seed, rng, size, system_token, system_token_size, &new_seed, &for_kernel); + err = mangle_random_seed(seed, rng, size, system_token, system_token_size, uefi_monotonic_counter, &new_seed, &for_kernel); if (EFI_ERROR(err)) return err;