Skip to content

Commit b11a124

Browse files
committed
Apply 0003-Implement-last-resort-method-in-pg_strong_random.patch
1 parent c770686 commit b11a124

File tree

1 file changed

+76
-0
lines changed

1 file changed

+76
-0
lines changed

src/port/pg_strong_random.c

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
#include "postgres_fe.h"
1919
#endif
2020

21+
#include "common/sha2.h"
22+
2123
#include <fcntl.h>
2224
#include <unistd.h>
2325

@@ -29,6 +31,9 @@
2931
#endif
3032

3133
static bool random_from_file(char *filename, void *buf, size_t len);
34+
#ifndef WIN32
35+
static bool random_from_std(void *dst, size_t len);
36+
#endif
3237

3338
#ifdef WIN32
3439
/*
@@ -72,6 +77,67 @@ random_from_file(char *filename, void *buf, size_t len)
7277
return true;
7378
}
7479

80+
#ifndef WIN32
81+
/*
82+
* This is not available on Windows, and the cryptography standards available
83+
* there are enough anyway to generate randomness.
84+
*/
85+
#include <sys/time.h>
86+
#include <time.h>
87+
88+
/*
89+
* Generate some random data using environment data as entropy
90+
* through SHA-256. All the other methods failed, this can be used
91+
* as a last resort method even if it is predictible, and rather
92+
* slow compared to the rest.
93+
*/
94+
static bool
95+
random_from_std(void *dst, size_t len)
96+
{
97+
pid_t pid;
98+
size_t remaining = len;
99+
100+
/* process ID */
101+
pid = getpid();
102+
103+
/*
104+
* Compute a random value by generating successive chunks worth
105+
* of PG_SHA256_DIGEST_LENGTH bytes.
106+
*/
107+
while (remaining != 0)
108+
{
109+
int x;
110+
struct timeval tv;
111+
pg_sha256_ctx ctx;
112+
uint8 sha_buf[PG_SHA256_DIGEST_LENGTH];
113+
114+
pg_sha256_init(&ctx);
115+
pg_sha256_update(&ctx, (uint8 *) &pid, sizeof(pid));
116+
117+
/* time */
118+
gettimeofday(&tv, NULL);
119+
pg_sha256_update(&ctx, (uint8 *) &tv, sizeof(tv));
120+
121+
/* pointless, but should not hurt */
122+
x = random();
123+
pg_sha256_update(&ctx, (uint8 *) &x, sizeof(x));
124+
pg_sha256_final(&ctx, sha_buf);
125+
126+
/* copy the chunk generated in the result */
127+
memcpy(dst, sha_buf, Min(remaining, PG_SHA256_DIGEST_LENGTH));
128+
129+
/* and prepare to loop further */
130+
if (remaining >= PG_SHA256_DIGEST_LENGTH)
131+
remaining -= PG_SHA256_DIGEST_LENGTH;
132+
else
133+
remaining = 0;
134+
dst = (uint8 *) dst + PG_SHA256_DIGEST_LENGTH;
135+
}
136+
137+
return true;
138+
}
139+
#endif
140+
75141
/*
76142
* pg_strong_random
77143
*
@@ -86,6 +152,8 @@ random_from_file(char *filename, void *buf, size_t len)
86152
* 2. Windows' CryptGenRandom() function
87153
* 3. /dev/urandom
88154
* 4. /dev/random
155+
* 5. Use the internal, predictible method computing a value through SHA-256
156+
* with system-related entropy.
89157
*
90158
* Returns true on success, and false if none of the sources
91159
* were available. NB: It is important to check the return value!
@@ -143,6 +211,14 @@ pg_strong_random(void *buf, size_t len)
143211
if (random_from_file("/dev/random", buf, len))
144212
return true;
145213

214+
#ifndef WIN32
215+
/*
216+
* As final method, generate some randomness using the in-house method.
217+
*/
218+
if (random_from_std(buf, len))
219+
return true;
220+
#endif
221+
146222
/* None of the sources were available. */
147223
return false;
148224
}

0 commit comments

Comments
 (0)