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...@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.


* 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 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: 0001-Replace-PostmasterRandom-with-a-stronger-source-seco.patch
Description: application/download

Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:

Reply via email to