use kernel command line as a source of randomness

By looking at the kernel source code diff it seems this doesn’t need a kernel parameter (such as hypothetically entropy=[blob of random data].

We could ship an /etc/default/grub.d configuration file snippet in package security-misc that reads some random data from /dev/random [1] and adds it to kernel command line. [2]

How many bytes should be added?

Sized between 1024 bytes and 4096 bytes are being discussed.

How would we encode the random data? (because should not write random characters directly into config file - these can mess up terminal and/or editors)

  • sha512? hash using sha512 every x bytes?
  • base64?
  • something better?

Should this kernel parameter be the first in line or last in line? This is because when users want to change kernel command line in grub boot menu (press E to edit) they would see a huge random blob of data which is not pretty and bad usability. That makes me wonder if this is a good idea at all.

Isn’t there a “second kernel command line” or similar? Or any saner interface for the bootloader to pass entropy to the kernel? Maybe something similar to early-rng-init-tools for better entropy? would be a better idea?

systemd-boot loader supports passing a random seed file to the kernel when being used with EFI. More on that here:

I haven’t found anything for grub and/or non-EFI. Yet have to read that Tails ticket.


[1] /dev/random vs. /dev/urandom

[2] The disadvantages of this implementation are:

  • visible in /proc/cmdline Quote:
    • Why not pass the boot loader random seed via kernel command line instead of as EFI variable?

    • The kernel command line is accessible to unprivileged processes via /proc/cmdline . It’s not desirable if unprivileged processes can use this information to possibly gain too much information about the current state of the kernel’s entropy pool.

  • stays static until update-grub is re-run (mostly only at kernel upgrade)
    • non-ideal but not a problem because no entropy added to the kernel mix can in theory worsen the quality of Linux entropy.
  • perhaps better to re-generate this file on every boot but I don’t see yet a way to do so in an atomic way - meaning not break booting if grub config file generation is interrupted due to power loss or reboot
1 Like

Quote Persistent Storage feature: random seed (#11897) · Issues · tails / tails · GitLab

Updated by cypherpunks 6 months ago

Some explanation would help. My sources for using 512 bytes are https://linux.die.net/man/4/urandom and linux/drivers/char/random.c at master · torvalds/linux · GitHub. Of course restoring any entropy at all is better than none, but why do you think 32 or 16 would be “plenty”?

The pool is 512 bytes in size, but you only need 32 or 16 bytes (256 or 128 bits, respectively) to achieve cryptographic security. In fact, /dev/urandom since Linux 4.8 uses ChaCha20 with a 256 bit (32 byte) seed.

Can anyone confirm this from an authoritative source? 32 bit / 4 byte would be more than small enough for being added to kernel command line without breaking usability.

An answer to that would also help with twuewand - a truerand algorithm for generating entropy - Whonix integration.

2 Likes

Fortunately grub supports variables.

Therefore probably no usability issue at grub boot menu. Will test soon.

The question is just how much can we uglify /proc/cmdline?

See this command:

hexdump -n "4096" -e '"%02X"' /dev/random

Would be OK if /proc/cmdline starts with that random string and ends with actual kernel command line parameters?

3 Likes

That’s far too big. I don’t think users want to be harassed by a massive wall of random text when checking their boot parameters.

32 bytes would be far better. AFAIK, it is enough to achieve cryptographic security hence why AES only uses key sizes between 128-256 bits.

1 Like

Maybe Blake2 can be used here in a roundabout way on Debian since b2sum isn’t packaged for some reason:

https://www.pycryptodome.org/en/latest/src/hash/blake2b.html

Blake2 is much faster and CPU efficient than SHA-2

Questions:
*Does grub have python bindings/
*Can grub take more than 1 kernel command line

1 Like

I will probable publish a working implementation soon. Using grub load_env with filename and whitelsited variable name.

I don’t think this needs CPU efficiency. Hashing 4096 bytes with sha512 takes ~ 0.002 seconds.

I wouldn’t know what that would be useful for here.

I’ve not found any references that Linux can take that.

1 Like

What problem are you trying to solve with this?

If you’re only worried about things using /dev/urandom before it’s seeded, then:

  1. That’s not actually a big problem with reasonably recent Linux on X86 processors, because the kernel will use the CPU’s RDSEED/RDRAND instructions to seed even /dev/urandom before returning any data to userspace. So unless your CPU has been subverted, or unless there’s a bug in what’s actually a pretty simple code path, you’ll never get bad randomness on X86. Really there’s only an issue on ARM.

  2. If you still care about the /dev/urandom early read problem, and you are willing to trust /dev/random, then you can always just create an early systemd unit to copy data from /dev/random into /dev/urandom. It’ll slow your boot down a lot, though. Actually you don’t even have to do that; all you really need to do is to wait untily you are able to read a single byte from /dev/urandom, or get data from the getrandom() system call, because neither of those will return until both /dev/random and /dev/urandom are fully seeded (the two are pretty intertwined in the kernel). If you do this, be aware that systemd will use some /dev/urandom data very early, but it only uses it to protect against some weird local denial of service attacks that probably aren’t major threats for Whonix.

Regardless, it’s “not considered good practice” to rely on seed that can be read by any process in the system, nor to rely on seed that could be the same between two boots.

1 Like

We can use apparmor-profile-everything to hide /proc/cmdline and grub config files from all processes.

dmesg is already restricted to root and we can restrict it further with a kernel patch. I’ve already had a patch to do this for a while now.

I’m not aware of another way to read the boot parameters that we haven’t covered or wouldn’t be trivial to fix.

The grub config can be regenerated during boot via a systemd service so the next boot would have a unique seed.

We can use apparmor-profile-everything to hide /proc/cmdline and grub config files from all processes.

I suppose you could. But you’d be doing an awful lot of work… and a lot of unreliable work that might leak, might silently (albeit not catastrophically) break when something else in the next release of Debian gives out access to this historically non-secret information, and might break something else that relies on having the information. I mean, even if you did put seed on the command line, I’m not sure “not considered good practice” is worth all that effort.

Maybe that’s colored by my seeing putting seed on the command line as a low-value move to begin with. Since I don’t see why you should do it at all, it’s hard for me to see why you’d want to make the investment to protect it.

I guess my basic problem is that I’m still not understanding what problem you want to solve. You seem to be willing to take on a lot of complexity for this, and I don’t know what’s motivating that.

The grub config can be regenerated during boot via a systemd service so the next boot would have a unique seed.

… but that relies on the in-VM /dev/random device. If you do it at boot, it’s not clear it’ll provide much more seed entropy than just reading a byte from /dev/random at boot and not trying to keep the state between boots.

State-keeping in the workstation VM is also one more thing to break if you ever want to support that VM being amnesic (which I think would be a very high-value move). So it doesn’t seem desirable to become reliant on such state for anything you would care about enough to do all this work in the first place.

In the world I’ve always lived in, persisting random seed from run to run of a program, a VM, a host, or whatever, has been something you did out of desperation when you didn’t have enough good entropy available to you. That’s just not the case on a modern X86 processor, even inside a VM. And even on ARM or whatever, it’d be more satisfying to get the seed from the host via a virtual hardware RNG. My memory is hazy, but I think VirtualBox and KVM both have those.

But maybe I’m just missing something major.

1 Like

I’d need to remove ,cmdline from apparmor-profile-everything/etc/apparmor.d/abstractions/init-systemd at master · Kicksecure/apparmor-profile-everything · GitHub and add r to apparmor-profile-everything/etc/apparmor.d/abstractions/dangerous-files at master · Kicksecure/apparmor-profile-everything · GitHub

A total change of 9 characters. Not that much work.

I don’t see how Debian can leak this when we’ve plugged all the kernel APIs that do.

Unless Debian ships a kernel exploit in the next version, I doubt it can leak this.

Boot parameters are only needed for debugging. Normal applications won’t need it.

I’m just giving ideas on how to protect it if it were to be implemented. I’m not saying it should be implemented.

Kernel logs and boot parameters were going to be restricted anyway.

GRUB can’t run commands at boot. The value has to be pre-defined.

Kernel will use randomness from kernel command line anyhow. See links in initial post in this forum thread. [1]

This is similar to systemd-random-seed.service. Just happens earlier.

Disadvantages:

  • does not work for first boot
  • does not work for live boot but no worse than too due to [1]

Rationale: “use as many sources of entropy as possible in case any breaks down”.

See also: twuewand - a truerand algorithm for generating entropy - Whonix integration

We distrust (set random.trust_cpu=off kernel boot parameter) RDRAND. See:
Entropy, Randomness, /dev/random vs /dev/urandom, Entropy Sources, Entropy Gathering Daemons, RDRAND

I.e. it is used but not credited.

We don’t have issues with boot speed / performance thanks to haveged / jitterentropy-rng (user space daemon and kernel module).

1 Like

Did you know…

?

1 Like

KVM has virtio-rng which is enabled by default in Whonix KVM but I haven’t found any reference that VirtualBox supports virtio-rng.

1 Like

Just now added…


Quote Goal:

Assumption is that any source of randomness could be (sometimes) flawed (weak / predictable / broken / compromised) (in some situations). Such as either in VMs and/or n the host.

Therefore the goal was established to - simplified - “make use of as many sources of entropy as possible”.

Ideally, sources of randomness should also be coming from different devices.

CPU is already being used as a source of entropy by haveged and jitterentropy-rng. That’s two implementations using the same source using the same device. Adding more entropy generation daemons that are based on CPU - or even worse - based on jitter - is therefore undesirable.

It would be better to tap into other entropy sources such as from noise generated from audio, video, etc. if we can verify these to be good sources of entropy. By implementing that, even if one source of randomness (retrospectively) turns out to be flawed, quality of system entropy should still be excellent.


Quote use kernel command line as a source of randomness:

Introduction

[1] Kernel will use kernel command line as a source of randomness in any case - whether a random seed is added to kernel command line or not. Sources:

adding a random seed to kernel command line

Goal: see goal.

Design:

  • Do not credit entropy since this might be dangerous if something goes wrong.
  • Non-goal: Fixing performance related early entropy issue since there is none.
  • systemd unit file drop-in for systemd-random-seed.service [archive] by adding
    • ExecStartPost to refresh seed early at boot to avoid re-using the same one.
    • ExecStopPost to mix in new entropy that was collected since last boot.
  • add a randomseed= parameter to kernel command line
    • The kernel does not support a randomseed= parameter directly. But the kernel uses kernel command line as a source of entropy. The keyword randomseed= could be replaced with any other keyword. This is just for self-documenting purposes. I.e. by reading the web searching for and reading the scripts, clues are given why what is being done.

Similar to:

  • Adding a random seed to kernel command line would be similar to systemd-random-seed.service [archive] (enabled by systemd and Debian default) but happening earlier already at boot stage of initial ramdisk. systemd-random-seed.service by default also does not credit entropy.
  • Also similar to early-rng-init-tootls but without its potential security issues since not crediting entropy.

Disadvantages:

  • Does not work at first boot.
  • Does not work for live boot but no worse than too due to [1].

Advantages:

  • Same as systemd-random-seed.service but already available at boot stage initial ramdisk.

Thanks for the feedback. Could you please review the now documented rationale? All points were addressed?

2 Likes

I think that explains it quite well. I still don’t really agree with it, but I now understand what you’re trying to do. Thank you.

3 Likes