arc4random vs RAND_pseudo_bytes

Robert Connolly robert at linuxfromscratch.org
Wed Sep 5 02:31:15 PDT 2007


I looked around in openssl/crypto/rand/ and couldn't figure out what is 
different about RAND_bytes() and RAND_pseudo_bytes().

I made a small program to use RAND_bytes() and RAND_pseudo_bytes():

$ cat ossl_rand.c
#include <stdlib.h>
#include <stdio.h>
#include <openssl/rand.h>

int main ()
{
  unsigned char buf[8];
  if (RAND_bytes(buf, 8) == 0) { exit(1); }

  printf("RAND_bytes is %s\n", buf);

  return 0;
}

Same thing for "RAND_pseudo_bytes", just substitute "RAND_bytes". Compile 
with:

gcc -o ossl_rand ossl_rand.c -O2 -Wall -lcrypto -static

I ran strace(1) on both, there is no difference. They both use /dev/urandom. 
So I copied a statically linked strace program and did:

sudo chroot $(pwd) ./strace ./ossl_rand
and
sudo chroot $(pwd) ./strace ./ossl_rand_pseudo

Both fail because they can't 
open /dev/urandom, /dev/random, /dev/srandom, /var/run/egd-pool, /dev/egd-pool, 
etc... the program exit's with 1 because RAND_*bytes are failing.

Then I tried symlinking /dev/zero to /dev/urandom. The output still changed 
with each runtime, I think because there's a getpid()/arc4random() stirred 
into RAND_poll() in crypto/rand/rand_unix.c before /dev/urandom is attempted.

I didn't find the algorithm used by the OpenSSL prng, but assuming there is a 
cryptographic quality algorithm used the prng should always pass randomness 
tests as long as the seed doesn't repeat... even if using getpid() 
exclusively this would be very rare unless the test is run for a very very 
long time.

So anyway, I'm not seeing the difference between RAND_bytes() and 
RAND_pseudo_bytes(), despite what the manual page says. Maybe the manual is 
out of date, or very generic for systems without urandom (windows, vms, and 
who knows what else).

The RAND_bytes(3) page says RAND_bytes() will error if it doesn't get enough 
seed to generate an unpredictable sequence, but it looks like the getpid() in 
RAND_poll() is giving RAND_bytes() enough entropy, so RAND_bytes() is never 
going to fail unless maybe it gets a 2 digit getpid.

The advantage arc4random() has is that it never returns an error, and always 
returns something. But I just noticed that the arc4random() patch in the book 
doesn't stir getpid/gettimeofday unconditionally, so symlinking /dev/zero 
to /dev/urandom makes arc4random() return the same number. I'll need to fix 
this. It's an extra syscall but it's more failsafe.

The advantage to RAND_*bytes() is that it will fail if no random device is 
found. This can be a very good idea. I can't think of any application, other 
than solitaire card games, where I would want the program to keep going if it 
can't find /dev/urandom.

But arc4random() seems to have it's place, to provide a failsafe 
if /dev/urandom exists but is outputting 0's. It's a replacement for 
getpid/gettimeofday.

It's 05:30, I'm starting to go blind.

robert
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: <http://lists.linuxfromscratch.org/pipermail/hlfs-dev/attachments/20070905/37f3a6dc/attachment.sig>


More information about the hlfs-dev mailing list