Project

General

Profile

Feature #16891

Ensure enough entropy is available when setting up persistence

Added by segfault 5 months ago. Updated about 2 months ago.

Status:
Confirmed
Priority:
Elevated
Assignee:
Category:
-
Target version:
-
Start date:
Due date:
% Done:

0%

Feature Branch:
Type of work:
Code
Blueprint:
Starter:
Affected tool:

Description

Copying from the description of #11897:

Given I just installed Tails on a USB stick
When I boot it for the first time
Then I want to have good entropy to create the persistent storage

This was supposed to be solved by #11897, but now that our recommended way to install Tails on a USB stick is via the USB Image instead of the Tails Installer, #11897 won't help much to solve this.


Related issues

Related to Tails - Feature #11897: Persist a random seed across boots Needs Validation 11/04/2016

History

#1 Updated by segfault 5 months ago

#2 Updated by segfault 5 months ago

I propose that in tails-persistence-setup, when creating the encrypted persistence partition, we check that the current entropy of the kernel's RNG is high enough to provide good random numbers for the LUKS key generation.

I found that the luks_format function in src/plugins/crypto.c in the libblockdev repo, which is used via udisks to format the persistent volume as LUKS, takes a min_entropy parameter and blocks until this amount of entropy is available. Unfortunately, udisks doesn't allow specifying this parameter and always sets it to 0.

But we can easily do this check ourselves, by reading /proc/sys/kernel/random/entropy_avail. This file contains the available entropy, in bits (see http://man7.org/linux/man-pages/man4/random.4.html). We should check that this is >= 256 (for the 256 bit AES key).

#3 Updated by segfault 3 months ago

  • Priority changed from Normal to Elevated

I'm raising the priority, because I think that this is a serious issue, since it can lead to predictable keys being used for the persistence partition.

It shouldn't be too hard to implement this, what I imagine is that we add a step that is executed before the create_persistence_partition step, to:

  • Check [ $(cat /proc/sys/kernel/random/entropy_avail) -ge 256 ] in a while loop every few seconds
  • Show "Waiting for entropy..." in the "Setup Tails persistent volume" dialog

I would like to implement this, but it requires writing Perl, which I'm still really bad at. I already spent many hours on the tails-persistence-setup code for #11529, so I know that it's a really inefficient use of my time.

@intrigeri, maybe you could work on this once you find the time. I'm sure it will be a lot easier for you.

#4 Updated by intrigeri about 2 months ago

Hi segfault! And sorry for the delay…

intrigeri, maybe you could work on this once you find the time. I'm sure it will be a lot easier for you.

Sure, this could be another fun coding project for a rainy Sunday.

But wait, I'm wondering if this extra code path will ever be run, because I'm not sure it is possible that /proc/sys/kernel/random/entropy_avail ever gets lower than 256 in real-world scenarios.

This did ring a bell so I did a notmuch search, which pointed me to discussions on tails-dev in 2012, where several people claimed that haveged avoids this kind of situations. I've just repeated an experiment that anonym did back then to support this argument: cat /dev/random | pv > /dev/null. Just like anonym reported back then, I get a stable rate of about 2 MB/s; additionally, I monitored /proc/sys/kernel/random/entropy_avail while this pipeline was running, and it rarely fell below 256, and only for very brief intervals (less than 1 second).

I suspect that in real-world scenarios, with no process trying to exhaust /dev/random continuously, the risk that /proc/sys/kernel/random/entropy_avail falls below 256 is extremely low, as long as we ship haveged.

Now, you seem to think the opposite is true, and you're more knowledgeable than me in this area, so I'm wondering what I missed :)

Cheers!

#5 Updated by segfault about 2 months ago

intrigeri wrote:

But wait, I'm wondering if this extra code path will ever be run, because I'm not sure it is possible that /proc/sys/kernel/random/entropy_avail ever gets lower than 256 in real-world scenarios.

This did ring a bell so I did a notmuch search, which pointed me to discussions on tails-dev in 2012, where several people claimed that haveged avoids this kind of situations. I've just repeated an experiment that anonym did back then to support this argument: cat /dev/random | pv > /dev/null. Just like anonym reported back then, I get a stable rate of about 2 MB/s; additionally, I monitored /proc/sys/kernel/random/entropy_avail while this pipeline was running, and it rarely fell below 256, and only for very brief intervals (less than 1 second).

I suspect that in real-world scenarios, with no process trying to exhaust /dev/random continuously, the risk that /proc/sys/kernel/random/entropy_avail falls below 256 is extremely low, as long as we ship haveged.

I'm not worrying about the entropy falling too low [1], but that we never gathered enough good entropy before the persistent partition is created.

It's possible that haveged bumps the the entropy counter to >=256 immediately after boot. But I don't really like that, because gathering entropy from userspace in general [2], and via haveged in particular [3], has renowned critics. I would sleep better if we would just wait until the kernel seeded the CSPRNG - but I don't know how long users might have to wait if we did that.

[1] Once the CSPRNG was seeded with good entropy, it can generate a lot of cryptograpically secure random numbers from it. That's why, in that case, it is safe to use /dev/urandom instead of /dev/random (see https://www.2uo.de/myths-about-urandom/). That's also the behavior of getrandom(): http://man7.org/linux/man-pages/man2/getrandom.2.html.

[2] https://twitter.com/mjg59/status/1181428407466385409

[3] https://lwn.net/Articles/525459/

#6 Updated by segfault about 2 months ago

I just read the "What about the claims I have heard that haveged doesn't work as advertised?" in the official haveged FAQ (https://www.issihosts.com/haveged/faq.html), which leaves me shocked. The statement "If the output cannot be distinguished from a TRNG at run time, it's a TRNG." is so utterly ridiculous that I wouldn't trust the author of that sentence on any matter related to cryptography.

Also available in: Atom PDF