summaryrefslogtreecommitdiff
path: root/contrib
diff options
context:
space:
mode:
authorHeikki Linnakangas2016-10-18 13:28:23 +0000
committerHeikki Linnakangas2016-10-18 13:28:23 +0000
commitfaae1c918e8aaae034eaf3ea103fcb6ba9adc5ab (patch)
tree4d2739ac51be02b6701d9d9c14e7e1058f8d5fe0 /contrib
parent7d3235ba42f8d5fc70c58e242702cc5e2e3549a6 (diff)
Revert "Replace PostmasterRandom() with a stronger way of generating randomness."
This reverts commit 9e083fd4683294f41544e6d0d72f6e258ff3a77c. That was a few bricks shy of a load: * Query cancel stopped working * Buildfarm member pademelon stopped working, because the box doesn't have /dev/urandom nor /dev/random. This clearly needs some more discussion, and a quite different patch, so revert for now.
Diffstat (limited to 'contrib')
-rw-r--r--contrib/pgcrypto/Makefile2
-rw-r--r--contrib/pgcrypto/internal.c40
-rw-r--r--contrib/pgcrypto/random.c247
3 files changed, 264 insertions, 25 deletions
diff --git a/contrib/pgcrypto/Makefile b/contrib/pgcrypto/Makefile
index 76c2f1aa17..805db7626b 100644
--- a/contrib/pgcrypto/Makefile
+++ b/contrib/pgcrypto/Makefile
@@ -1,7 +1,7 @@
# contrib/pgcrypto/Makefile
INT_SRCS = md5.c sha1.c sha2.c internal.c internal-sha2.c blf.c rijndael.c \
- fortuna.c pgp-mpi-internal.c imath.c
+ fortuna.c random.c pgp-mpi-internal.c imath.c
INT_TESTS = sha2
OSSL_SRCS = openssl.c pgp-mpi-openssl.c
diff --git a/contrib/pgcrypto/internal.c b/contrib/pgcrypto/internal.c
index ad942f733a..02ff976c25 100644
--- a/contrib/pgcrypto/internal.c
+++ b/contrib/pgcrypto/internal.c
@@ -626,6 +626,8 @@ static time_t check_time = 0;
static void
system_reseed(void)
{
+ uint8 buf[1024];
+ int n;
time_t t;
int skip = 1;
@@ -640,34 +642,24 @@ system_reseed(void)
else if (check_time == 0 ||
(t - check_time) > SYSTEM_RESEED_CHECK_TIME)
{
- uint8 buf;
-
check_time = t;
/* roll dice */
- px_get_random_bytes(&buf, 1);
- skip = (buf >= SYSTEM_RESEED_CHANCE);
-
- /* clear 1 byte */
- px_memset(&buf, 0, sizeof(buf));
- }
- if (!skip)
- {
- /*
- * fortuna_add_entropy passes the input to SHA-256, so there's no
- * point in giving it more than 256 bits of input to begin with.
- */
- uint8 buf[32];
-
- if (!pg_strong_random(buf, sizeof(buf)))
- ereport(ERROR,
- (errcode(ERRCODE_INTERNAL_ERROR),
- errmsg("could not acquire random data")));
- fortuna_add_entropy(buf, sizeof(buf));
-
- seed_time = t;
- px_memset(buf, 0, sizeof(buf));
+ px_get_random_bytes(buf, 1);
+ skip = buf[0] >= SYSTEM_RESEED_CHANCE;
}
+ /* clear 1 byte */
+ px_memset(buf, 0, sizeof(buf));
+
+ if (skip)
+ return;
+
+ n = px_acquire_system_randomness(buf);
+ if (n > 0)
+ fortuna_add_entropy(buf, n);
+
+ seed_time = t;
+ px_memset(buf, 0, sizeof(buf));
}
int
diff --git a/contrib/pgcrypto/random.c b/contrib/pgcrypto/random.c
new file mode 100644
index 0000000000..d72679e412
--- /dev/null
+++ b/contrib/pgcrypto/random.c
@@ -0,0 +1,247 @@
+/*
+ * random.c
+ * Acquire randomness from system. For seeding RNG.
+ *
+ * Copyright (c) 2001 Marko Kreen
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * contrib/pgcrypto/random.c
+ */
+
+#include "postgres.h"
+
+#include "px.h"
+#include "utils/memdebug.h"
+
+/* how many bytes to ask from system random provider */
+#define RND_BYTES 32
+
+/*
+ * Try to read from /dev/urandom or /dev/random on these OS'es.
+ *
+ * The list can be pretty liberal, as the device not existing
+ * is expected event.
+ */
+#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) \
+ || defined(__NetBSD__) || defined(__DragonFly__) \
+ || defined(__darwin__) || defined(__SOLARIS__) \
+ || defined(__hpux) || defined(__HPUX__) \
+ || defined(__CYGWIN__) || defined(_AIX)
+
+#define TRY_DEV_RANDOM
+
+#include <fcntl.h>
+#include <unistd.h>
+
+static int
+safe_read(int fd, void *buf, size_t count)
+{
+ int done = 0;
+ char *p = buf;
+ int res;
+
+ while (count)
+ {
+ res = read(fd, p, count);
+ if (res <= 0)
+ {
+ if (errno == EINTR)
+ continue;
+ return PXE_DEV_READ_ERROR;
+ }
+ p += res;
+ done += res;
+ count -= res;
+ }
+ return done;
+}
+
+static uint8 *
+try_dev_random(uint8 *dst)
+{
+ int fd;
+ int res;
+
+ fd = open("/dev/urandom", O_RDONLY, 0);
+ if (fd == -1)
+ {
+ fd = open("/dev/random", O_RDONLY, 0);
+ if (fd == -1)
+ return dst;
+ }
+ res = safe_read(fd, dst, RND_BYTES);
+ close(fd);
+ if (res > 0)
+ dst += res;
+ return dst;
+}
+#endif
+
+/*
+ * Try to find randomness on Windows
+ */
+#ifdef WIN32
+
+#define TRY_WIN32_GENRAND
+#define TRY_WIN32_PERFC
+
+#include <windows.h>
+#include <wincrypt.h>
+
+/*
+ * this function is from libtomcrypt
+ *
+ * try to use Microsoft crypto API
+ */
+static uint8 *
+try_win32_genrand(uint8 *dst)
+{
+ int res;
+ HCRYPTPROV h = 0;
+
+ res = CryptAcquireContext(&h, NULL, MS_DEF_PROV, PROV_RSA_FULL,
+ (CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET));
+ if (!res)
+ res = CryptAcquireContext(&h, NULL, MS_DEF_PROV, PROV_RSA_FULL,
+ CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET);
+ if (!res)
+ return dst;
+
+ res = CryptGenRandom(h, RND_BYTES, dst);
+ if (res == TRUE)
+ dst += RND_BYTES;
+
+ CryptReleaseContext(h, 0);
+ return dst;
+}
+
+static uint8 *
+try_win32_perfc(uint8 *dst)
+{
+ int res;
+ LARGE_INTEGER time;
+
+ res = QueryPerformanceCounter(&time);
+ if (!res)
+ return dst;
+
+ memcpy(dst, &time, sizeof(time));
+ return dst + sizeof(time);
+}
+#endif /* WIN32 */
+
+
+/*
+ * If we are not on Windows, then hopefully we are
+ * on a unix-like system. Use the usual suspects
+ * for randomness.
+ */
+#ifndef WIN32
+
+#define TRY_UNIXSTD
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <time.h>
+#include <unistd.h>
+
+/*
+ * Everything here is predictible, only needs some patience.
+ *
+ * But there is a chance that the system-specific functions
+ * did not work. So keep faith and try to slow the attacker down.
+ */
+static uint8 *
+try_unix_std(uint8 *dst)
+{
+ pid_t pid;
+ int x;
+ PX_MD *md;
+ struct timeval tv;
+ int res;
+
+ /* process id */
+ pid = getpid();
+ memcpy(dst, (uint8 *) &pid, sizeof(pid));
+ dst += sizeof(pid);
+
+ /* time */
+ gettimeofday(&tv, NULL);
+ memcpy(dst, (uint8 *) &tv, sizeof(tv));
+ dst += sizeof(tv);
+
+ /* pointless, but should not hurt */
+ x = random();
+ memcpy(dst, (uint8 *) &x, sizeof(x));
+ dst += sizeof(x);
+
+ /* hash of uninitialized stack and heap allocations */
+ res = px_find_digest("sha1", &md);
+ if (res >= 0)
+ {
+ uint8 *ptr;
+ uint8 stack[8192];
+ int alloc = 32 * 1024;
+
+ VALGRIND_MAKE_MEM_DEFINED(stack, sizeof(stack));
+ px_md_update(md, stack, sizeof(stack));
+ ptr = px_alloc(alloc);
+ VALGRIND_MAKE_MEM_DEFINED(ptr, alloc);
+ px_md_update(md, ptr, alloc);
+ px_free(ptr);
+
+ px_md_finish(md, dst);
+ px_md_free(md);
+
+ dst += 20;
+ }
+
+ return dst;
+}
+#endif
+
+/*
+ * try to extract some randomness for initial seeding
+ *
+ * dst should have room for 1024 bytes.
+ */
+unsigned
+px_acquire_system_randomness(uint8 *dst)
+{
+ uint8 *p = dst;
+
+#ifdef TRY_DEV_RANDOM
+ p = try_dev_random(p);
+#endif
+#ifdef TRY_WIN32_GENRAND
+ p = try_win32_genrand(p);
+#endif
+#ifdef TRY_WIN32_PERFC
+ p = try_win32_perfc(p);
+#endif
+#ifdef TRY_UNIXSTD
+ p = try_unix_std(p);
+#endif
+ return p - dst;
+}