Re: [RFC PATCH 0/2] Propagating reseed notifications to user space

Yann Droneaud
2023-09-17T13:43:18Z

Hi,

Le 23/08/2023 à 11:01, Babis Chalios a écrit :
> User space often implements PRNGs that use /dev/random as entropy
> source. We can not expect that this randomness sources stay completely
> unknown forever. For various reasons, the originating PRNG seed may
> become known at which point the PRNG becomes insecure for further random
> number generation. Events that can lead to that are for example fast
> computers reversing the PRNG function using a number of inputs or
> Virtual Machine clones which carry seed values into their clones.
>
> During LPC 2022 Jason, Alex, Michael and me brainstormed on how to
> atomically expose a notification to user space that it should reseed.
> Atomicity is key for the VM clone case. This patchset implements a
> potential path to do so.
>
> This patchset introduces an epoch value as the means of communicating to
> the guest the need to reseed. The epoch is a 32bit value with the
> following form:
>
> RNG epoch
> *-------------*---------------------*
> | notifier id | epoch counter value |
> *-------------*---------------------*
> 8 bits 24 bits
>
> Changes in this value signal moments in time that PRNGs need to be
> re-seeded. As a result, the intended use of the epoch from user space
> PRNGs is to cache the epoch value every time they reseed using kernel
> entropy, then control that its value hasn't changed before giving out
> random numbers. If the value has changed the PRNG needs to reseed before
> producing any more random bits.
>
> The API for getting hold of this value is offered through
> /dev/(u)random. We introduce a new ioctl for these devices, which
> creates an anonymous file descriptor. User processes can call the
> ioctl() to get the anon fd and then mmap it to a single page. That page
> contains the value of the epoch at offset 0.
>
> Naturally, random.c is the component that maintains the RNG epoch.
> During initialization it allocates a single global page which holds the
> epoch value. Moreover, it exposes an API to kernel subsystems
> (notifiers) which can report events that require PRNG reseeding.
> Notifiers register with random.c and receive an 8-bit notifier id (up to
> 256 subscribers should be enough) and a pointer to the epoch. Notifying,
> then, is equivalent to writing in the epoch address a new epoch value.
>
> Notifiers write epoch values that include the notifier ID on the higher
> 8 bits and increasing counter values on the 24 remaining bits. This
> guarantees that two notifiers cannot ever write the same epoch value,
> since notificator IDs are unique.
>
> The first patch of this series implements the epoch mechanism. It adds
> the logic in the random.c to maintain the epoch page and expose the
> user space facing API. It also adds the internal API that allows kernel
> systems to register as notifiers.

From userspace point of view, having to open /dev/random, ioctl, and mmap()
is a no-go for a (CS)PRNG embedded in libc for arc4random().

I'm biased, as I proposed to expose such seed epoch value to userspace through
getrandom() directly, relying on vDSO for reasonable performances, because
current's glibc arc4random() is somewhat to slow to be a general replacement
rand().

See
https://lore.kernel.org/all/cover.1673539719.git.ydroneaud@opteya.com/
https://lore.kernel.org/all/ae35afa5b824dc76c5ded98efcabc117e6dd3d70@opteya.com/

Reards.

--
Yann Droneaud