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 * Note: this code is run quite early in postmaster and backend startup;
10 * therefore, even when built for backend, it cannot rely on backend
11 * infrastructure such as elog() or palloc().
13 * Copyright (c) 1996-2020, PostgreSQL Global Development Group
16 * src/port/pg_strong_random.c
18 *-------------------------------------------------------------------------
28 #include <openssl/rand.h>
30 #ifdef USE_WIN32_RANDOM
34 #ifdef USE_WIN32_RANDOM
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(const 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)
109 * Check that OpenSSL's CSPRNG has been sufficiently seeded, and if not
110 * add more seed data using RAND_poll(). With some older versions of
111 * OpenSSL, it may be necessary to call RAND_poll() a number of times. If
112 * RAND_poll() fails to generate seed data within the given amount of
113 * retries, subsequent RAND_bytes() calls will fail, but we allow that to
114 * happen to let pg_strong_random() callers handle that with appropriate
117 #define NUM_RAND_POLL_RETRIES 8
119 for (i
= 0; i
< NUM_RAND_POLL_RETRIES
; i
++)
121 if (RAND_status() == 1)
123 /* The CSPRNG is sufficiently seeded */
130 if (RAND_bytes(buf
, len
) == 1)
135 * Windows has CryptoAPI for strong cryptographic numbers.
137 #elif defined(USE_WIN32_RANDOM)
140 if (!CryptAcquireContext(&hProvider
,
144 CRYPT_VERIFYCONTEXT
| CRYPT_SILENT
))
147 * On failure, set back to 0 in case the value was for some reason
153 /* Re-check in case we just retrieved the provider */
156 if (CryptGenRandom(hProvider
, len
, buf
))
162 * Read /dev/urandom ourselves.
164 #elif defined(USE_DEV_URANDOM)
165 if (random_from_file("/dev/urandom", buf
, len
))
170 /* The autoconf script should not have allowed this */
171 #error no source of random numbers configured