18
18
#include "postgres_fe.h"
19
19
#endif
20
20
21
+ #include "common/sha2.h"
22
+
21
23
#include <fcntl.h>
22
24
#include <unistd.h>
23
25
29
31
#endif
30
32
31
33
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
32
37
33
38
#ifdef WIN32
34
39
/*
@@ -72,6 +77,67 @@ random_from_file(char *filename, void *buf, size_t len)
72
77
return true;
73
78
}
74
79
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
+
75
141
/*
76
142
* pg_strong_random
77
143
*
@@ -86,6 +152,8 @@ random_from_file(char *filename, void *buf, size_t len)
86
152
* 2. Windows' CryptGenRandom() function
87
153
* 3. /dev/urandom
88
154
* 4. /dev/random
155
+ * 5. Use the internal, predictible method computing a value through SHA-256
156
+ * with system-related entropy.
89
157
*
90
158
* Returns true on success, and false if none of the sources
91
159
* were available. NB: It is important to check the return value!
@@ -143,6 +211,14 @@ pg_strong_random(void *buf, size_t len)
143
211
if (random_from_file ("/dev/random" , buf , len ))
144
212
return true;
145
213
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
+
146
222
/* None of the sources were available. */
147
223
return false;
148
224
}
0 commit comments