-
-
Notifications
You must be signed in to change notification settings - Fork 10.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RAND_DRBG uses uninitialized urandom read on linux #8215
Comments
This is not an error of openssl. Basically the kernel signals that the in-kernel CRNG was not yet fully initialized with sufficient entropy. |
The point is, if we use /dev/urandom to initialize the DRBG the kernel tells us that the |
I assume this is done when we call the
|
Ahm, well.... |
My understanding is that the However, there seems to be an important difference between
So I would guess that OpenSSL was seeding from |
Okay, if the getrandom syscall is not available we seed from /dev/urandom and only if that |
So, how about that?
|
I still don't think we should do this, we would hog the entropy pool by doing it. Just think of the OpenSSL testsuite where a lot of For the current Linux kernels the fact that As for older kernels without |
@kroeckx might know more about kernel CSPRNG details than I do. |
How does this affect the answer I gave |
It would be good to have more detailed information about the VxWorks randlib in general and the |
This is a really good question and I remember having discussed it with @kroeckx (IIRC) at some time: Currently the DRBG refuses to generate random bytes if it is in the error state(*), so it is crucial to check the return value of (*) The DRBG attempts an automatic error recovery by reseeding, but if that fails, it will remain in the error state. |
Citing myself from RAND(7):
|
getrandom() and getentropy() will always block until the kernel
CSPRNG has been initialized. If you have a kernel that supports
it, so >= 3.17, we should always use it. Only with an older kernel
should be fall back to using /dev/urandom.
I've actually had people report that the boot now hangs because of
this for some people, for instance openssh blocking until it can
get random data.
I don't think we should be using /dev/random at all. If
getrandom()/getentropy() is not available, /dev/random will
probably also do the wrong thing and cause things to hang, but
then hang all the time.
Reading 1 byte from /dev/random should also not be done by each
process. People that want to make sure that no application reads
from /dev/urandom before it's initialized should prevent those
applications from starting instead, by for instance reading 1 byte
during the boot process.
|
To actually be able to use getrandom on Linux if it's not provided
by glibc, you need to compile against recent enough kernel headers
so that SYS_getrandom is defined. Note that SYS_getrandom is
architecture specific.
|
According to the discussions I've had with the FIPS lab about entropy sources, this isn't correct. Calling a blocking If we need to use /dev/urandom, the only method I can think of to guarantee that it is properly seeded is via waiting for something like We should avoid /dev/random is we can, but we might not be able to do so. |
I'd put /dev/hwrng before /dev/prandom. /dev/prandom is a pseudo random generator like /dev/urandom and I don't believe claims about made about it being properly seeded.
/dev/srandom should be before /dev/urandom and perhaps even before /dev/random. It is a good source. |
That's good news. It seems that I was too pessimistic. :-) |
What about prediction resistance? It was always Kurt's opinion (not mine) that a prediction resistance request needs to be propagated upwards. This would imply that in this case, |
Please do not ever use /dev/random in openssl by default. That would be simply not usable in any normal scenario where openssl is used throughout the system. |
It is OS business to ensure that the kernel RNG is properly seeded with entropy on system boot, openssl has no way to influence/enforce that (apart from using getrandom). To summarize - use getrandom/getentropy (without GRND_RANDOM flag of course) and if it is not available, use /dev/urandom. That's it. |
@t8m I quite agree. |
The problem with |
I think this does probably not do what was intended:
... because linux defines __NR_getrandom and glibc defines SYS_getrandom. |
@t8m please explain this? |
Update: |
Apart from the obvious blocking? |
Yes, we should use __NR_getrandom.
|
If my memory is correct, FIPS says that using the OS provided
entropy is fine, it does not talk about which interface you talk
to the OS. I don't see why FIPS should care about /dev/urandom vs
getrandom(), other than that Linux's /dev/urandom is broken and
returns data before it has been initialized. But I think making
sure that is initialized is up to the OS, not OpenSSL.
|
Why is that a problem? You either wait until there's enough entropy, or you decide to go ahead and be insecure. The default configuration, since most users are not knowledgeable, should be to wait. |
And again I ask, what is the alternative? Competition for a scarce resource, in a land of naive programmers. |
Just wait until the initial seeding has completed and then simply use it's output without blocking any further (that's what In this context you might find the following blog post interesting: https://www.2uo.de/myths-about-urandom The author's opinion might not be authoritative, but |
Yes, but and that is only after the |
According to #8023 (comment) |
MAYBE we should only read 1 byte from there and after that continue with /dev/urandom. |
Guys, some of you seem a bit confused about what
|
FIPS 140-2 Implementation Guidance 7.15 Entropy Assessment makes a clear distinction:
There is quite a bit more wordage around this but it is the non-blocking nature before initial seeding that is pointed to as the problem. |
I'm pretty sure that this won't guarantee that /dev/urandom has been properly seeded. NIST doesn't say anything about |
I agree about /dev/prandom, and would actually remove it, it is seeded from /dev/urandom and
I don't know anything about srandom, is this a BSD thing? Is it similar to /dev/hwrng, the seed |
I think you meant to provide a link to getentropy.c, not getrandom.c, but thanks for the link. Indeed, I was not aware that (But note that the two links above also show that you are you are just almost right: both functions are library routines: while |
At least with recent linux kernel that is the case. |
Theodore Ts'o explains in the commit message of commit c6e9d6f388947986 that the behaviour of
|
Idea: |
A promising idea, indeed. I'd be interested to learn whether this trick helps to get rid of the "uninitialized urandom read" warning. |
If you use getentropy() or getrandom(), the interface actually
blocks until the it has been initialized, on all OSs. It starts to
return data the same time /dev/random starts to return data the
first time.
If you use /dev/urandom on Linux, it reads wether it's initialized
or not. If you read /dev/random on Linux, it blocks until it's
initialiazed, and then says you remove entropy once you read
anything, which doesn't make sense with the current PRNG in the
kernel (it might have with the old one). Both /dev/random and
/dev/urandom on Linux really are broken. And they don't fix
/dev/urandom because it caused a hang in some applications (which
now hang anyway because they switched to getrandom()).
If you can't use getrandom()/getentropy(), you can work around
/dev/urandom's broken behaviour by reading 1 byte from
/dev/random. This 1 byte only needs to be read by 1 application
during the boot process, not every application should be doing
that. Linux distro's could fix this by adding that 1 byte read
somewhere in the boot sequence, but none do because the boot would
hang. We could do this in OpenSSL, or for FIPS we could just
document that it's up to the OS to make sure this has been done.
This is the only problem FIPS has with the use of /dev/urandom,
just like everybody else.
Recent Linux kernels actually are able to initialize the RNG within
a few seconds of booting.
On some other OSs, /dev/random and /dev/urandom are actually sane,
there is no difference between them, and only return data after
it's been initialized.
In short, just switch to getrandom()/getentropy().
|
Sure, this is just a fallback, when that is not available, but from the emotional reaction |
Use select to wait for /dev/random in readable state, but do not actually read anything from /dev/random, use /dev/urandom first. Use linux define __NR_getrandom instead of the glibc define SYS_getrandom, in case the kernel headers are more current than the glibc headers. Fixes openssl#8215
Hmm, this does not really work as expected, (using v4.14-stable with RT patch):
|
Yes, it is a BSD device. From the man page:
|
MD5 ? |
That's what the man page I found said. I wouldn't be surprised if the algorithm had been changed since. I wouldn't consider MD5 as being broken as an entropy whitening function -- collisions are very remote from reversibility. I'd still advocate moving to something more recent of course. |
Yes, that is the main reason. And for the reason that always-blocking /dev/random fighting for entropy is a broken concept on multi-process multi-user system it is often also blocked by security mechanisms such as SELinux. Basically /dev/random could be accepted as a special choice for user but it should never be used by default in general purpose crypto library. |
Because the entropy gathered is directed to various pools and never re-used. Roughly said, first the CRNG (which feeds /dev/urandom and getrandom()) is half-initialized with 64 bits of entropy (or so), then the entropy gathered goes to initialize the /dev/random entropy pool and only after that one is initialized, it goes to complete the CRNG initialization. It might not be exactly like that and it changed a little over various kernel versions but you can get the picture. |
The idea is to wait on /dev/random using select(), but to never
actually read from it.
I'm sure opening /dev/random will fail in some cases, and we
should then just continue like we did previously.
|
If my understanding of the process is current, this will have a race condition, whereby something else could consume the collection pool's entropy before it is sent to urandom pool. Still, it is a better approach than doing nothing. |
Use select to wait for /dev/random in readable state, but do not actually read anything from /dev/random, use /dev/urandom first. Use linux define __NR_getrandom instead of the glibc define SYS_getrandom, in case the kernel headers are more current than the glibc headers. Fixes #8215 Reviewed-by: Kurt Roeckx <[email protected]> (Merged from #8251) (cherry picked from commit 38023b8)
This message can be seen when openssl s_server is started early after reboot:
I have seen this with linux v4.18, and v4.14-stable.
Previous linux versions are also affected, but do not report the error.
The text was updated successfully, but these errors were encountered: