PostgreSQL Source Code
git master
Loading...
Searching...
No Matches
pg_strong_random.c
Go to the documentation of this file.
1
/*-------------------------------------------------------------------------
2
*
3
* pg_strong_random.c
4
* generate a cryptographically secure random number
5
*
6
* Our definition of "strong" is that it's suitable for generating random
7
* salts and query cancellation keys, during authentication.
8
*
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().
12
*
13
* Copyright (c) 1996-2026, PostgreSQL Global Development Group
14
*
15
* IDENTIFICATION
16
* src/port/pg_strong_random.c
17
*
18
*-------------------------------------------------------------------------
19
*/
20
21
#include "
c.h
"
22
23
#include <fcntl.h>
24
#include <
unistd.h
>
25
#include <
sys/time.h
>
26
27
/*
28
* pg_strong_random & pg_strong_random_init
29
*
30
* Generate requested number of random bytes. The returned bytes are
31
* cryptographically secure, suitable for use e.g. in authentication.
32
*
33
* Before pg_strong_random is called in any process, the generator must first
34
* be initialized by calling pg_strong_random_init(). Initialization is a no-
35
* op for all supported randomness sources, it is kept to maintain backwards
36
* compatibility with extensions.
37
*
38
* We rely on system facilities for actually generating the numbers.
39
* We support a number of sources:
40
*
41
* 1. OpenSSL's RAND_bytes()
42
* 2. Windows' CryptGenRandom() function
43
* 3. /dev/urandom
44
*
45
* Returns true on success, and false if none of the sources
46
* were available. NB: It is important to check the return value!
47
* Proceeding with key generation when no random data was available
48
* would lead to predictable keys and security issues.
49
*/
50
51
52
53
#ifdef USE_OPENSSL
54
55
#include <openssl/rand.h>
56
57
void
58
pg_strong_random_init
(
void
)
59
{
60
/* No initialization needed */
61
}
62
63
bool
64
pg_strong_random
(
void
*
buf
,
size_t
len
)
65
{
66
int
i
;
67
68
/*
69
* Check that OpenSSL's CSPRNG has been sufficiently seeded, and if not
70
* add more seed data using RAND_poll(). With some older versions of
71
* OpenSSL, it may be necessary to call RAND_poll() a number of times. If
72
* RAND_poll() fails to generate seed data within the given amount of
73
* retries, subsequent RAND_bytes() calls will fail, but we allow that to
74
* happen to let pg_strong_random() callers handle that with appropriate
75
* error handling.
76
*/
77
#define NUM_RAND_POLL_RETRIES 8
78
79
for
(
i
= 0;
i
<
NUM_RAND_POLL_RETRIES
;
i
++)
80
{
81
if
(
RAND_status
() == 1)
82
{
83
/* The CSPRNG is sufficiently seeded */
84
break
;
85
}
86
87
RAND_poll
();
88
}
89
90
if
(
RAND_bytes
(
buf
,
len
) == 1)
91
return
true
;
92
return
false
;
93
}
94
95
#elif WIN32
96
97
#include <wincrypt.h>
98
/*
99
* Cache a global crypto provider that only gets freed when the process
100
* exits, in case we need random numbers more than once.
101
*/
102
static
HCRYPTPROV
hProvider
= 0;
103
104
void
105
pg_strong_random_init
(
void
)
106
{
107
/* No initialization needed on WIN32 */
108
}
109
110
bool
111
pg_strong_random
(
void
*
buf
,
size_t
len
)
112
{
113
if
(
hProvider
== 0)
114
{
115
if
(!
CryptAcquireContext
(&
hProvider
,
116
NULL
,
117
MS_DEF_PROV
,
118
PROV_RSA_FULL
,
119
CRYPT_VERIFYCONTEXT
|
CRYPT_SILENT
))
120
{
121
/*
122
* On failure, set back to 0 in case the value was for some reason
123
* modified.
124
*/
125
hProvider
= 0;
126
}
127
}
128
/* Re-check in case we just retrieved the provider */
129
if
(
hProvider
!= 0)
130
{
131
if
(
CryptGenRandom
(
hProvider
,
len
,
buf
))
132
return
true
;
133
}
134
return
false
;
135
}
136
137
#else
/* not USE_OPENSSL or WIN32 */
138
139
/*
140
* Without OpenSSL or Win32 support, just read /dev/urandom ourselves.
141
*/
142
143
void
144
pg_strong_random_init
(
void
)
145
{
146
/* No initialization needed */
147
}
148
149
bool
150
pg_strong_random
(
void
*
buf
,
size_t
len
)
151
{
152
int
f;
153
char
*p =
buf
;
154
ssize_t
res;
155
156
f =
open
(
"/dev/urandom"
,
O_RDONLY
, 0);
157
if
(f == -1)
158
return
false
;
159
160
while
(
len
)
161
{
162
res =
read
(f, p,
len
);
163
if
(res <= 0)
164
{
165
if
(
errno
==
EINTR
)
166
continue
;
/* interrupted by signal, just retry */
167
168
close
(f);
169
return
false
;
170
}
171
172
p += res;
173
len
-= res;
174
}
175
176
close
(f);
177
return
true
;
178
}
179
#endif
c.h
close
#define close(a)
Definition
win32.h:12
read
#define read(a, b, c)
Definition
win32.h:13
i
int i
Definition
isn.c:77
len
const void size_t len
Definition
pg_crc32c_sse42.c:28
pg_strong_random
bool pg_strong_random(void *buf, size_t len)
Definition
pg_strong_random.c:150
pg_strong_random_init
void pg_strong_random_init(void)
Definition
pg_strong_random.c:144
buf
static char buf[DEFAULT_XLOG_SEG_SIZE]
Definition
pg_test_fsync.c:71
fb
static int fb(int x)
Definition
preproc-init.c:92
time.h
unistd.h
EINTR
#define EINTR
Definition
win32_port.h:361
src
port
pg_strong_random.c
Generated on Tue Jan 27 2026 06:13:18 for PostgreSQL Source Code by
1.9.8