Issue #15039 has been updated by jeremyevans0 (Jeremy Evans).


Freaky (Thomas Hurst) wrote:
> jeremyevans0 (Jeremy Evans) wrote:
> 
> > On OpenBSD, arc4random is not really a userspace PRNG in the sense that it is reseeded on a regular basis using new entropy data from the kernel
> 
> It runs code in userspace to stretch a small amount of entropy into a large amount.  I think that's a fair definition of "userspace PRNG", no?

srand/rand is the classic userspace PRNG, where all future output is based only on the initial input.

arc4random_buf(3) is basically like fread(3), where getentropy(2) is like read(2).  Would you consider fread(3) userspace I/O simply because it buffers?

> In this case, that "regular basis" is every 1.6MB:
> 
>     rs->rs_count = 1600000;
> 
> Why not just reseed OpenSSL's CSPRNG that often, if this was sufficient to mitigate the concerns in #9569?

Why do something more complex when the library function handles correctly for you (at least in OpenBSD's case)?

> > I have no opinion on what the Random.urandom and SecureRandom implementations should default to on other operating systems, but on OpenBSD they should keep the current default of arc4random_buf(3).
> 
> I think users should have a reasonable expectation of the semantics of these APIs remaining the same across systems.  arc4random keeps the state predominantly in the Ruby process: you're one Spectre/Cloudbleed-style attack away from the next million bytes of SecureRandom output being guessable by an attacker and one fork-detection-mishap away from two processes generating large quantities of identical randomness.

If you are susceptible to a memory attack like Spectre/Cloudbleed, you probably have bigger issues than just arc4random_buf.

At least on OpenBSD, fork-detection-mishaps can't happen due to MAP_INHERIT_ZERO.

> Failing that, I'd at *least* like to see arc4random only used on platforms where it's confirmed to be reasonably trustworthy.

That seems fine to me.  I can confirm it is "reasonably trustworthy" on OpenBSD, not sure about other operating systems.

> > Looking at FreeBSD 11.2 (https://github.com/freebsd/freebsd/blob/releng/11.2/lib/libc/gen/arc4random.c), it appears to also reseed on a regular basis
> 
> In that regard it's exactly the same as on OpenBSD - it reseeds every 1.6MB.  The data in between all comes from stretching that small pool of entropy using a broken stream cipher dating from the late 1980's.  And yes, it has a dubious silent fail-dangerous fallback path if its seeding efforts fail, and who knows how good it is at detecting fork (also fail-dangerous judging by comments in OpenBSD compat code).

Those may be reasons to choose something different on FreeBSD, but I make no recommendation in that area.

> > From the link to the Rust OSRng, it uses getentropy(2) for OpenBSD and kern.arandom for FreeBSD, which appears to be similar to what OpenBSD and FreeBSD use internally in their arc4random_buf(3) implementations.
> 
> Yes, but that's *all* they use.  And they'll fail if they can't get it, rather than falling back to getpid, gettimeofday and whatever junk happens to be on the stack...

On OpenBSD, arc4random_buf cannot fail. It returns void, and doesn't have a fallback implementation as the kernel can always provide randomness when stirring.

Have you reviewed the OpenSSL PRNG implementation for old and recent versions of OpenSSL to confirm that they are not susceptible to any of the issues you are concerned with?

----------------------------------------
Bug #15039: Random.urandom and SecureRandom arc4random use
https://bugs.ruby-lang.org/issues/15039#change-73769

* Author: Freaky (Thomas Hurst)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
* ruby -v: 
* Backport: 2.3: UNKNOWN, 2.4: UNKNOWN, 2.5: UNKNOWN
----------------------------------------
Random.urandom defaults to arc4random() on a lot of platforms, including FreeBSD.

On all currently released versions of FreeBSD, arc4random() is, as the name suggests, a dubious ARC4-based userspace PRNG dating from circa 1997.  Given the entire point of #9569 was that using the userspace CSPRNG in OpenSSL over /dev/urandom or equivalent is a bad idea, this seems to mean it's regressed to an *even worse* state on these platforms.  Even in cases where it's using something more modern (FreeBSD 12, OpenBSD), it's still a userspace CSPRNG.

If that's fine, we might as well *pick a known-good one* and use that everywhere.  Like, say, OpenSSL's.

Since the conclusion of #9569 seems to have been otherwise, I'd suggest dropping arc4random() as a potential source for Random.urandom due to it not matching the desired semantics.

Rust's OsRng seems a good template for alternative _syscall implementations: https://docs.rs/rand/0.5.5/rand/rngs/struct.OsRng.html#platform-sources



-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>