diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/include/pg_config.h.in | 9 | ||||
-rw-r--r-- | src/port/pg_strong_random.c | 201 | ||||
-rw-r--r-- | src/tools/msvc/Solution.pm | 3 |
3 files changed, 83 insertions, 130 deletions
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in index fb270df678a..de8f838e536 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -862,9 +862,6 @@ /* Define to 1 to build with BSD Authentication support. (--with-bsd-auth) */ #undef USE_BSD_AUTH -/* Define to use /dev/urandom for random number generation */ -#undef USE_DEV_URANDOM - /* Define to build with ICU support. (--with-icu) */ #undef USE_ICU @@ -887,9 +884,6 @@ /* Define to build with OpenSSL support. (--with-openssl) */ #undef USE_OPENSSL -/* Define to use OpenSSL for random number generation */ -#undef USE_OPENSSL_RANDOM - /* Define to 1 to build with PAM support. (--with-pam) */ #undef USE_PAM @@ -914,9 +908,6 @@ /* Define to select unnamed POSIX semaphores. */ #undef USE_UNNAMED_POSIX_SEMAPHORES -/* Define to use native Windows API for random number generation */ -#undef USE_WIN32_RANDOM - /* Define to select Win32-style semaphores. */ #undef USE_WIN32_SEMAPHORES diff --git a/src/port/pg_strong_random.c b/src/port/pg_strong_random.c index 6d85f50b7c8..12bbd7fb08b 100644 --- a/src/port/pg_strong_random.c +++ b/src/port/pg_strong_random.c @@ -24,107 +24,15 @@ #include <unistd.h> #include <sys/time.h> -#ifdef USE_OPENSSL_RANDOM -#include <openssl/rand.h> -#endif -#ifdef USE_WIN32_RANDOM -#include <wincrypt.h> -#endif - -#ifdef USE_WIN32_RANDOM -/* - * Cache a global crypto provider that only gets freed when the process - * exits, in case we need random numbers more than once. - */ -static HCRYPTPROV hProvider = 0; -#endif - -#if defined(USE_DEV_URANDOM) -/* - * Read (random) bytes from a file. - */ -static bool -random_from_file(const char *filename, void *buf, size_t len) -{ - int f; - char *p = buf; - ssize_t res; - - f = open(filename, O_RDONLY, 0); - if (f == -1) - return false; - - while (len) - { - res = read(f, p, len); - if (res <= 0) - { - if (errno == EINTR) - continue; /* interrupted by signal, just retry */ - - close(f); - return false; - } - - p += res; - len -= res; - } - - close(f); - return true; -} -#endif - /* - * pg_strong_random_init - * - * Initialize the randomness state of "strong" random numbers. This is invoked - * *after* forking a process, and should include initialization steps specific - * to the chosen random source to prove fork-safety. - */ -void -pg_strong_random_init(void) -{ -#if defined(USE_OPENSSL) - /* - * Make sure processes do not share OpenSSL randomness state. We need to - * call this even if pg_strong_random is implemented using another source - * for random numbers to ensure fork-safety in our TLS backend. This is no - * longer required in OpenSSL 1.1.1 and later versions, but until we drop - * support for version < 1.1.1 we need to do this. - */ - RAND_poll(); -#endif - -#if defined(USE_OPENSSL_RANDOM) - /* - * In case the backend is using the PRNG from OpenSSL without being built - * with support for OpenSSL, make sure to perform post-fork initialization. - * If the backend is using OpenSSL then we have already performed this - * step. The same version caveat as discussed in the comment above applies - * here as well. - */ -#ifndef USE_OPENSSL - RAND_poll(); -#endif - -#elif defined(USE_WIN32_RANDOM) - /* no initialization needed for WIN32 */ - -#elif defined(USE_DEV_URANDOM) - /* no initialization needed for /dev/urandom */ - -#else -#error no source of random numbers configured -#endif -} - -/* - * pg_strong_random + * pg_strong_random & pg_strong_random_init * * Generate requested number of random bytes. The returned bytes are * cryptographically secure, suitable for use e.g. in authentication. * + * Before pg_strong_random is called in any process, the generator must first + * be initialized by calling pg_strong_random_init(). + * * We rely on system facilities for actually generating the numbers. * We support a number of sources: * @@ -132,21 +40,32 @@ pg_strong_random_init(void) * 2. Windows' CryptGenRandom() function * 3. /dev/urandom * - * The configure script will choose which one to use, and set - * a USE_*_RANDOM flag accordingly. - * * Returns true on success, and false if none of the sources * were available. NB: It is important to check the return value! * Proceeding with key generation when no random data was available * would lead to predictable keys and security issues. */ -bool -pg_strong_random(void *buf, size_t len) + + + +#ifdef USE_OPENSSL + +#include <openssl/rand.h> + +void +pg_strong_random_init(void) { /* - * When built with OpenSSL, use OpenSSL's RAND_bytes function. + * Make sure processes do not share OpenSSL randomness state. This is no + * longer required in OpenSSL 1.1.1 and later versions, but until we drop + * support for version < 1.1.1 we need to do this. */ -#if defined(USE_OPENSSL_RANDOM) + RAND_poll(); +} + +bool +pg_strong_random(void *buf, size_t len) +{ int i; /* @@ -174,11 +93,26 @@ pg_strong_random(void *buf, size_t len) if (RAND_bytes(buf, len) == 1) return true; return false; +} - /* - * Windows has CryptoAPI for strong cryptographic numbers. - */ -#elif defined(USE_WIN32_RANDOM) +#elif WIN32 + +#include <wincrypt.h> +/* + * Cache a global crypto provider that only gets freed when the process + * exits, in case we need random numbers more than once. + */ +static HCRYPTPROV hProvider = 0; + +void +pg_strong_random_init(void) +{ + /* No initialization needed on WIN32 */ +} + +bool +pg_strong_random(void *buf, size_t len) +{ if (hProvider == 0) { if (!CryptAcquireContext(&hProvider, @@ -201,17 +135,48 @@ pg_strong_random(void *buf, size_t len) return true; } return false; +} - /* - * Read /dev/urandom ourselves. - */ -#elif defined(USE_DEV_URANDOM) - if (random_from_file("/dev/urandom", buf, len)) - return true; - return false; +#else /* not USE_OPENSSL or WIN32 */ -#else - /* The autoconf script should not have allowed this */ -#error no source of random numbers configured -#endif +/* + * Without OpenSSL or Win32 support, just read /dev/urandom ourselves. + */ + +void +pg_strong_random_init(void) +{ + /* No initialization needed */ +} + +bool +pg_strong_random(void *buf, size_t len) +{ + int f; + char *p = buf; + ssize_t res; + + f = open("/dev/urandom", O_RDONLY, 0); + if (f == -1) + return false; + + while (len) + { + res = read(f, p, len); + if (res <= 0) + { + if (errno == EINTR) + continue; /* interrupted by signal, just retry */ + + close(f); + return false; + } + + p += res; + len -= res; + } + + close(f); + return true; } +#endif diff --git a/src/tools/msvc/Solution.pm b/src/tools/msvc/Solution.pm index 17e480546cf..22d6abd3674 100644 --- a/src/tools/msvc/Solution.pm +++ b/src/tools/msvc/Solution.pm @@ -475,7 +475,6 @@ sub GenerateFiles USE_ASSERT_CHECKING => $self->{options}->{asserts} ? 1 : undef, USE_BONJOUR => undef, USE_BSD_AUTH => undef, - USE_DEV_URANDOM => undef, USE_ICU => $self->{options}->{icu} ? 1 : undef, USE_LIBXML => undef, USE_LIBXSLT => undef, @@ -483,7 +482,6 @@ sub GenerateFiles USE_LLVM => undef, USE_NAMED_POSIX_SEMAPHORES => undef, USE_OPENSSL => undef, - USE_OPENSSL_RANDOM => undef, USE_PAM => undef, USE_SLICING_BY_8_CRC32C => undef, USE_SSE42_CRC32C => undef, @@ -492,7 +490,6 @@ sub GenerateFiles USE_SYSV_SEMAPHORES => undef, USE_SYSV_SHARED_MEMORY => undef, USE_UNNAMED_POSIX_SEMAPHORES => undef, - USE_WIN32_RANDOM => 1, USE_WIN32_SEMAPHORES => 1, USE_WIN32_SHARED_MEMORY => 1, WCSTOMBS_L_IN_XLOCALE => undef, |