1 /*-------------------------------------------------------------------------
4 * generate a cryptographically secure random number
6 * Our definition of "strong" is that it's suitable for generating random
7 * salts and query cancellation keys, during authentication.
9 * Copyright (c) 1996-2017, PostgreSQL Global Development Group
12 * src/port/pg_strong_random.c
14 *-------------------------------------------------------------------------
20 #include "postgres_fe.h"
28 #include <openssl/rand.h>
36 * Cache a global crypto provider that only gets freed when the process
37 * exits, in case we need random numbers more than once.
39 static HCRYPTPROV hProvider = 0;
42 #if defined(USE_DEV_URANDOM)
44 * Read (random) bytes from a file.
47 random_from_file(char *filename, void *buf, size_t len)
53 f = open(filename, O_RDONLY, 0);
59 res = read(f, p, len);
63 continue; /* interrupted by signal, just retry */
81 * Generate requested number of random bytes. The returned bytes are
82 * cryptographically secure, suitable for use e.g. in authentication.
84 * We rely on system facilities for actually generating the numbers.
85 * We support a number of sources:
87 * 1. OpenSSL's RAND_bytes()
88 * 2. Windows' CryptGenRandom() function
91 * The configure script will choose which one to use, and set
92 * a USE_*_RANDOM flag accordingly.
94 * Returns true on success, and false if none of the sources
95 * were available. NB: It is important to check the return value!
96 * Proceeding with key generation when no random data was available
97 * would lead to predictable keys and security issues.
100 pg_strong_random(void *buf, size_t len)
103 * When built with OpenSSL, use OpenSSL's RAND_bytes function.
105 #if defined(USE_OPENSSL_RANDOM)
106 if (RAND_bytes(buf, len) == 1)
111 * Windows has CryptoAPI for strong cryptographic numbers.
113 #elif defined(USE_WIN32_RANDOM)
116 if (!CryptAcquireContext(&hProvider,
120 CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
123 * On failure, set back to 0 in case the value was for some reason
129 /* Re-check in case we just retrieved the provider */
132 if (CryptGenRandom(hProvider, len, buf))
138 * Read /dev/urandom ourselves.
140 #elif defined(USE_DEV_URANDOM)
141 if (random_from_file("/dev/urandom", buf, len))
146 /* The autoconf script should not have allowed this */
147 #error no source of random numbers configured