Random number generation, take two

From: Heikki Linnakangas <hlinnaka(at)iki(dot)fi>
To: pgsql-hackers <pgsql-hackers(at)postgresql(dot)org>
Subject: Random number generation, take two
Date: 2016-11-29 13:02:54
Message-ID: 5da1f3d0-423d-8bfc-da68-bcee018bdfa6@iki.fi
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Ok, here's my second attempt at refactoring random number generation.
Previous attempt crashed and burned, see
https://www.postgresql.org/message-id/E1bw3g3-0003st-6M@gemulon.postgresql.org.
This addresses the issues pointed out in that thread.

The goals are:

* Have a pg_strong_random() function available in both frontend and
backend. (Frontend support needed by upcoming SCRAM patches)

* Use a stronger generator for query cancel keys and MD5 salts than
PostmasterRandom() that's used today.

* Still work on platforms that don't have a supported random source.

Autoconf
--------

* Configure chooses the implementation to use: OpenSSL, Windows native,
or /dev/urandom, in that order. You can also force it, by specifying
USE_OPENSSL_RANDOM=1, USE_WIN32_RANDOM=1 or USE_DEV_URANDOM=1 on the
configure command line. That's useful for testing.

This is better than trying all the options at runtime, because it's
better to fail early, at configure. Also, if e.g. OpenSSL's RAND_bytes()
for some reason fails at runtime, you don't want to silently fall back
to reading /dev/urandom. It really shouldn't fail in the first place, so
we'd rather fail visibly so that the admin or developer can investigate.

The auto-detection will not work when cross-compiling, because checking
for the presence of /dev/urandom on the build host doesn't tell us
whether it will be present in the target. autoconf will give an error,
but you can override that with USE_DEV_URANDOM=1.

* On platforms that don't have OpenSSL nor /dev/urandom (Tom's HP-UX
box, pademelon), configure will error out. But you can use
--disable-strong-random to fall back to a less-secure built-in
implementation. This is not done automatically, to avoid falling back to
a less secure implementation by accident.

* When building with --disable-strong-random, the pg_strong_random()
function is not available at all. Callers need to use #ifdef
HAVE_STRONG_RANDOM blocks if they want to use a fallback. This is again
to make sure that no extension, or built-in code either for that matter,
will accidentally fall back to the less secure implementation.

* Remove the support for /dev/random (only support /dev/urandom). I
don't think we have any platforms where /dev/urandom is not present, but
/dev/random is. If we do, the buildfarm will tell us, but until then
let's keep it simple.

Fallback implementation (with --disable-strong-random)
-----------

In postmaster, the algorithm is similar to the existing
PostmasterRandom() function. It's based on the built-in PRNG, seeded by
postmaster and first backend start time. It's been rewritten to fit the
rest of the code better, however.

In backends, there is a new function, pg_backend_random(). It also uses
the built-in PRNG, but the seed is shared between all backends, in
shared memory. (Otherwise all backends would inherit the same seed from
postmaster.)

pgcrypto
--------

pgcrypto doesn't have the same requirements for "strongness" as cancel
keys and MD5 salts have. pgcrypto uses random numbers for generating
salts, too, which I think has similar requirements. But it also uses
random numbers for generating encryption keys, which I believe ought to
be harder to predict. If you compile with --disable-strong-random, do we
want the encryption key generation routines to fail, or to return
known-weak keys?

This patch removes the Fortuna algorithm, that was used to generate
fairly strong random numbers, if OpenSSL was not present. One option
would be to keep that code as a fallback. I wanted to get rid of that,
since it's only used on a few old platforms, but OTOH it's been around
for a long time with little issues.

As this patch stands, it removes Fortuna, and returns known-weak keys,
but there's a good argument to be made for throwing an error instead.

Phew, this has been way more complicated than it seemed at first. Thoughts?

- Heikki

Attachment Content-Type Size
0001-Replace-PostmasterRandom-with-a-stronger-source-seco.patch application/x-download 62.0 KB

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Stephen Frost 2016-11-29 14:03:42 Re: tiny psql doc inconsistency
Previous Message Fabien COELHO 2016-11-29 12:56:26 tiny psql doc inconsistency