[PATCH ustream-ssl] ustream-mbedtls: Use getrandom() instead of /dev/urandom
Hauke Mehrtens
hauke at hauke-m.de
Sun Feb 19 12:06:15 PST 2023
Hi Torsten,
Sorry for the late answer, I forgot about this mail thread.
On 1/30/23 10:57, Torsten Duwe wrote:
> Hi Hauke!
>
> On Sun, 29 Jan 2023 17:08:38 +0100
> Hauke Mehrtens <hauke at hauke-m.de> wrote:
>
>>> drivers/char/random.c lines 1240- ...
>>> * Reading from /dev/urandom has the same functionality as calling
>>> * getrandom(2) with flags=GRND_INSECURE. Because it does not block
>>> * waiting for the RNG to be ready, it should not be used.
>>>
>>> Haven't audited mbedtls, but I assume it reads urandom for "lesser"
>>> entropy when needed. In any case, getrandom(out, len, GRND_INSECURE)
>>> would be the proper replacement.
>>>
>>> Torsten
>>
>> Hi Torsten,
>>
>> The mapage says this:
>> > By default, getrandom() draws entropy from the urandom source
>> > (i.e., the same source as the /dev/urandom device). This
>> > behavior can be changed via the flags argument.
>> https://man7.org/linux/man-pages/man2/getrandom.2.html
>>
>> GRND_INSECURE is also not documented in the man page.
>
> Well, it exists in the kernel source and headers...
>
>> The option was added to the Linux kernel 5.6 here:
>> https://git.kernel.org/linus/75551dbf112c992bc6c99a972990b3f272247e23
>>
>> The documentation says
>> > GRND_INSECURE Return non-cryptographic random bytes
>> We want to use the random bytes in mbedtls for cryptographic
>> operations. I think giving no flags is the correct option here.
>>
>> I think the behavior of /dev/random changed some years ago. This
>> article described it a bit: https://lwn.net/Articles/808575/
>
> That's only the internal workings.
> BTW, the mentioned quote of Andy Lutomirski applies here in some sense.
> You read away the true entropy and might even block on it when pseudo-
> randomness might suffice, see below.
>
>> As far as I understood the code, giving no flags will guarantee that
>> the random pool is initialized (crng_ready() returns true) and
>> otherwise it is the same as using GRND_INSECURE. As we use it for
>> cryptographic operations I think we should give no flags.
>
> "cryptographic operations" is a wide area. Some randomness is required,
> to varying degrees, for long-term keys, session keys, IVs and padding.
ustreamss uses the randomness to generate session keys (including
ephemeral keys), IVs and padding. The long term keys are generated in a
different application.
> Especially for long living keys, each end every bit should be totally
> unpredictable, which should correspond to read an appropriate amount
> from /dev/random. IVs and padding can be generated from a pseudo-RNG
> whose initial state is "uncertain enough", usually /dev/urandom.
>
> GIT is cool.
> c6e9d6f388947986 2014-Jul-17 tytso: introduce getrandom(2) system call
> 75551dbf112c992b 2019-Dec-23 luto: add GRND_INSECURE ...
> 48446f198f9adcb4 2019-Dec-23 luto: ignore GRND_RANDOM
>
> The first commit also has a man page in the comment, which is probably
> what was recorded. The second one changes the no-flags behaviour, away
> from the man page text you quoted.
>
> Someone once mentioned on LKML that drivers/char/random.c needs better
> maintenance... ;)
>
> I had a quick look at mbedtls and its usage of the provided rng
> function. It generates not only padding and IVs, but also session keys.
> Especially on OpenWRT these are a trade-off IMHO. OpenWRT supports a
> lot of hardware that is low on entropy at boot (MIPS anyone?) Do you
> want to block early ssh sessions, maybe even for minutes, or would you
> rather risk eavesdropping on those early connections?
>
> Depending on your choice for ustream, you can keep the proposed code,
> but please rename the functions to "random", not "urandom". Or you want
> to stick with the current urandom behaviour but then please add Luto's
> GRND_INSECURE flag to achieve that.
crng_ready() should only return false at bootup before the system got
enough random bits, afterwards it never returns false. Even without
GRND_INSECURE it will never run out of entropy.
I think we should wait with creating TLS sessions till we have enough
random data to do it securely. I tested this on a lantiq xrx200 (MIPS)
device and it was initialized much before the LAN interface was up.
The code in ustream-mbedtls.c was probably initially written when
/dev/random was still blocking when too much entropy was read out of the
pool.
I will rename the function.
Hauke
More information about the openwrt-devel
mailing list