Take the 2-minute tour ×
Information Security Stack Exchange is a question and answer site for Information security professionals. It's 100% free, no registration required.

I couldn't find the answer for the reason anywhere, even the wiki page doesn't explain it. This seems like using a PRNG for seeding an another PRNG. The first one (/dev/random) may itself be seeded by a PRNG.

I can 'understand' why the-randoption can't be used directly for generating keys, but I can't see the reason for the main sources. Many peoples say/dev/randomdon't produce enough output, which is wrong when it's entropy is feed by a daemon.

Do they consider/dev/randomnot to be a quality source?

share|improve this question

4 Answers 4

Reading bytes from a device can be troublesome (you have to account for syscall specificities, e.g. interrupted system calls) and can potentially be inefficient if reading many small chunks (a syscall has a non-negligible overhead). A custom software PRNG, seeded with bytes from /dev/urandom, gives more control over performance.

(Also, there might be a bit of NIH syndrome here, too.)

share|improve this answer
    
I also start wonder why they prevent aware professionals from using a generated file of random data (assuming better quality than openssl (I recognize this is not really realistic)). –  user2284570 Dec 24 '13 at 22:37
    
I think it's a mix of NIH and not trusting the OS to get it right. The performance issue could be fixed with relatively simply buffering instead of doing entropy gathering yourself. –  CodesInChaos Dec 24 '13 at 23:10
    
@CodesInChaos : Well, in my case, I wanted to just try clrngd mixed with rngd working with rdrand. I also don't really understand what is the purpose of the large table in /crypto/seed/seed.c of the openssl source tree. –  user2284570 Dec 24 '13 at 23:26
2  
That large table is the S-box (expanded) for the symmetric encryption algorithm SEED, specified in RFC 4269. It is an "official" algorithm from Korea. In OpenSSL source code, the SS[] array is defined in seed.c but used in macros defined in seed_locl.h (which is included by seed.c). –  Thomas Pornin Dec 25 '13 at 13:59

In general, reasons to not use the random source directly as presented include:

  • You may not require as many bits of entropy as you need bits. In this case, you can use the random bits to seed a pseudorandom number generator. This is most important when entropy is scarce (this constraint is becoming less relevant over time as dedicated hardware entropy sources become more common).
  • You do not want to trust that the random source is random. /dev/urandom in particular is not trustworthy because in guaranteeing that it wiill not block on low-entropy conditions, it fails to guarantee that the output is actually random. The manpage man 4 urandom has more information on this, including a cryptic allusion to an attack some government body may or may not have predicated on this condition. Suitability tests can be conducted on this data, or it can be mutated in some way to concentrate entropy, or different sources can be combined.
  • You wish to guarantee that a particular method for generating random numbers was used. This allows you to comply with any standard mandating this without having to rely on the Linux kernel developers to do it for you.

Consider also the concept of effective key size (the base-2 logarithm of the number of iterations of some optimal algorithm for breaking the key given some known item encrypted with it). There is obviously no purpose in consuming more bits of entropy than the effective key size, and doing so only depletes the entropy pool.

share|improve this answer
    
Nice! but i would prefer hearing an 'official' answer. –  user2284570 Dec 24 '13 at 22:10
    
I don't think one exists. It is an open-source project after all. Perhaps search their mailing list archives? –  Falcon Momot Dec 24 '13 at 22:18
    
I tried everything, but I am not a good finder for mail archives... Well, I don't understand the fact that open-source would be associated with decisions without reasons than proprietary. –  user2284570 Dec 24 '13 at 22:41

If you're asking why openssl rand or RAND_bytes() do not simply regurgitate /dev/random or /dev/urandom, it's because their function is to serve only as a PRNG, and they do exactly that:

The rand command outputs num pseudo-random bytes after seeding the random number generator once.

A correctly compiled and operating OpenSSL will read 32 bytes from /dev/urandom where available (and unless a hardware engine is specified instead), and use (some or all of) this to seed a PRNG. You can confirm if random or urandom are read with strace on a *nix system with:

$ strace -xe trace=file,read,write,close openssl rand 10
[...] 
open("/dev/urandom", O_RDONLY|O_NOCTTY|O_NONBLOCK) = 3
read(3, "\x26\x20\xfc\x61\x59\x81\xc9\x4d\xe5\x27\xab\xc2\x72\xb1"..., 32) = 32
close(3)                                = 0

As to why that is so, as a software library, OpenSSL cannot generate truly random numbers directly. The choices are to use a cryptographically secure PRNG with a good random seed (i.e. with OS harvested data from effectively random hardware events); or use a real hardware RNG. The Hardware section of the wiki explains how to do the latter, including how to access on-chip (Intel's RDRAND) RNG using the "engine" capability. Thomas Pornin's excellent answer here explains why a (correctly seeded, cryptographically-secure) PRNG is sufficient for most purposes: Evaluating the entropy gathering in a PRNG

If you want to be in charge of feeding random data to OpenSSL in a configurable way then using an EGD-style socket might be the easiest option. If you want to feed random numbers directly through the OpenSSL API, an engine is the "best" option (though you can cheat a little, example here)

I believe OpenSSL uses its own PRNG algorithm, unless you have FIPS enabled.

OpenSSL absolutely does use /dev/random when available: an excerpt from one of the answers in the FAQ:

All OpenSSL versions try to use /dev/urandom by default; starting with version 0.9.7, OpenSSL also tries /dev/random if /dev/urandom is not available.

and the wiki page you reference:

Initialization

OpenSSL will attempt to seed the random number generator automatically upon instantiation by calling RAND_poll. RAND_poll seeds the random number generator using a system-specific entropy source, which is /dev/urandom on UNIX-like operating systems, and is a combination of CryptGenRandom and other sources of entropy on Windows.


You also asked about whether this is "seeding a PRNG from a PRNG", it depends on how strictly you define a PRNG. A defining property of a PRNG is that it is deterministic, a PRNG has a "secret" starting point (defined by the seed), thereafter it is predictable (if you know that secret and the current iteration or, by extension the internal state). While a normal Linux random is clearly not a true "unobservable" or quantum RNG, it's not quite a normal PRNG either since its output quite quickly diverges from the deterministic values the initial seeding would result in. Conjecture aside, I think the contemporary term is a "PRNG with input", see this PDF paper, so a qualified "yes".

Since 0.9.7 OpenSSL defaults (DEVRANDOM define) to using in order: /dev/urandom, /dev/random, /dev/srandom (with 10ms non-blocking reads) and advises:

/* Use a random entropy pool device. Linux, FreeBSD and OpenBSD
 * have this. Use /dev/urandom if you can as /dev/random may block
 * if it runs out of random entries.  */

(OpenSSL-1.0.1e crypt/rand/rand_unix.c)

The contents of "random" should be used sparingly because it comes with some implied quality and is rate-limited. While urandom won't block, it's implied that its quality degrades with use. (At least on Linux, urandom is different on other platforms.)

Finally, some ancient history... OpenSSL is derived from SSLeay (OpenSSL was born at v0.9.0), and SSLeay (0.1 released April 1995) pre-dates commonly available OS managed (P)RNG. Linux was the first to get a random device in v1.3.30 in 1994, followed by FreeBSD 2.2 in 1995. The RAND_bytes() PRNG dates from this time, so it's interesting to see in the documentation (doc/rand.doc from 0.5.1b):

First up I will state the things I believe I need for a good RNG.
1) A good hashing algorithm to mix things up and to convert the RNG 'state'
   to random numbers.
2) An initial source of random 'state'.
3) The state should be very large. [...snip...]

which is followed by further discussion and a prescient summary:

So of the points raised, only 2 is not addressed, but sources of random data 
will always be a problem.

SSLeay first gained /dev/random support in version 0.5.3 (probably early 1996, change logs are a bit vague). Prior to that the PID, UID, timestamp and AFAICT, whatever was on the stack had to suffice. So RAND_bytes() was always a PRNG because that's a fast and portable solution. It uses what ever it can scavenge to seed the PRNG to give a useful quantity of random data, including OS provided randomness. When there's a hardware specific alternative to a PRNG, then a crypto engine can provide this functionality.

With regard to the behaviour of -rand I assume you mean when used with something like "openssl genrsa 2028". It probably just behaves this way because a moderate but indeterminate amount of random data is required (numbers are generated at random and tested for primality, a pair are needed) and the alternative was never considered useful (roughly 10-40 kiB of truly random data, as an educated guess).

share|improve this answer

In addition to Falcon's excellent answer:

[colin@localhost ~]$ time dd if=/dev/random of=/dev/null iflag=fullblock count=10 bs=32
10+0 records in
10+0 records out
320 bytes (320 B) copied, 32.0067 s, 0.0 kB/s
0.00user 0.00system 0:32.00elapsed 0%CPU (0avgtext+0avgdata 3104maxresident)k
0inputs+0outputs (0major+249minor)pagefaults 0swaps

[colin@localhost ~]$ time dd if=/dev/urandom of=/dev/null iflag=fullblock count=10 bs=32
10+0 records in
10+0 records out
320 bytes (320 B) copied, 0.000289421 s, 1.1 MB/s
0.00user 0.00system 0:00.00elapsed 0%CPU (0avgtext+0avgdata 3072maxresident)k
0inputs+0outputs (0major+247minor)pagefaults 0swaps

/dev/random might be very random, but its very, very slow!

share|improve this answer
    
You didn't read the comments I posted on mr.spuratic AT ALL! I'm using clrngdwhich allow me to get Mb of random data. Moreover If you empty the pool of /dev/random constantly, the quality of the random data will be very poor. –  user2284570 Apr 22 at 20:43

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.