blob: 46e3bb55941e2e575a657e51be580bdfa257d38e [file] [log] [blame]
Georg Brandl2daf6ae2012-02-20 19:54:16 +01001#include "Python.h"
2#ifdef MS_WINDOWS
Victor Stinner59f7fb22015-03-18 14:39:33 +01003# include <windows.h>
Martin Panterd2f87472016-07-29 04:00:44 +00004/* All sample MSDN wincrypt programs include the header below. It is at least
5 * required with Min GW. */
6# include <wincrypt.h>
Georg Brandl2daf6ae2012-02-20 19:54:16 +01007#else
Victor Stinner59f7fb22015-03-18 14:39:33 +01008# include <fcntl.h>
9# ifdef HAVE_SYS_STAT_H
10# include <sys/stat.h>
11# endif
Victor Stinnerdddf4842016-06-07 11:21:42 +020012# ifdef HAVE_LINUX_RANDOM_H
13# include <linux/random.h>
14# endif
Ned Deily7ae41122016-11-12 16:35:48 -050015# if defined(HAVE_GETRANDOM) || defined(HAVE_GETENTROPY)
Victor Stinnerbae2d622015-10-01 09:47:30 +020016# include <sys/random.h>
Ned Deily7ae41122016-11-12 16:35:48 -050017# endif
18# if !defined(HAVE_GETRANDOM) && defined(HAVE_GETRANDOM_SYSCALL)
Victor Stinner59f7fb22015-03-18 14:39:33 +010019# include <sys/syscall.h>
Victor Stinner59f7fb22015-03-18 14:39:33 +010020# endif
Georg Brandl2daf6ae2012-02-20 19:54:16 +010021#endif
22
Benjamin Peterson69e97272012-02-21 11:08:50 -050023#ifdef Py_DEBUG
24int _Py_HashSecret_Initialized = 0;
25#else
26static int _Py_HashSecret_Initialized = 0;
27#endif
Georg Brandl2daf6ae2012-02-20 19:54:16 +010028
29#ifdef MS_WINDOWS
Georg Brandl2daf6ae2012-02-20 19:54:16 +010030static HCRYPTPROV hCryptProv = 0;
31
32static int
33win32_urandom_init(int raise)
34{
Georg Brandl2daf6ae2012-02-20 19:54:16 +010035 /* Acquire context */
Martin v. Löwis3f50bf62013-01-25 14:06:18 +010036 if (!CryptAcquireContext(&hCryptProv, NULL, NULL,
37 PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
Georg Brandl2daf6ae2012-02-20 19:54:16 +010038 goto error;
39
40 return 0;
41
42error:
Victor Stinner4bad3b62016-08-16 15:23:58 +020043 if (raise) {
Georg Brandl2daf6ae2012-02-20 19:54:16 +010044 PyErr_SetFromWindowsErr(0);
Victor Stinner4bad3b62016-08-16 15:23:58 +020045 }
Georg Brandl2daf6ae2012-02-20 19:54:16 +010046 return -1;
47}
48
49/* Fill buffer with size pseudo-random bytes generated by the Windows CryptoGen
Victor Stinner4d6a3d62014-12-21 01:16:38 +010050 API. Return 0 on success, or raise an exception and return -1 on error. */
Georg Brandl2daf6ae2012-02-20 19:54:16 +010051static int
52win32_urandom(unsigned char *buffer, Py_ssize_t size, int raise)
53{
54 Py_ssize_t chunk;
55
56 if (hCryptProv == 0)
57 {
Victor Stinner4bad3b62016-08-16 15:23:58 +020058 if (win32_urandom_init(raise) == -1) {
Georg Brandl2daf6ae2012-02-20 19:54:16 +010059 return -1;
Victor Stinner4bad3b62016-08-16 15:23:58 +020060 }
Georg Brandl2daf6ae2012-02-20 19:54:16 +010061 }
62
63 while (size > 0)
64 {
65 chunk = size > INT_MAX ? INT_MAX : size;
Victor Stinner0c083462013-11-15 23:26:25 +010066 if (!CryptGenRandom(hCryptProv, (DWORD)chunk, buffer))
Georg Brandl2daf6ae2012-02-20 19:54:16 +010067 {
68 /* CryptGenRandom() failed */
Victor Stinner4bad3b62016-08-16 15:23:58 +020069 if (raise) {
Georg Brandl2daf6ae2012-02-20 19:54:16 +010070 PyErr_SetFromWindowsErr(0);
Victor Stinner4bad3b62016-08-16 15:23:58 +020071 }
Georg Brandl2daf6ae2012-02-20 19:54:16 +010072 return -1;
73 }
74 buffer += chunk;
75 size -= chunk;
76 }
77 return 0;
78}
Georg Brandl2daf6ae2012-02-20 19:54:16 +010079
Martin Panter39b10252016-06-10 08:07:11 +000080/* Issue #25003: Don't use getentropy() on Solaris (available since
Victor Stinnere66987e2016-09-06 16:33:52 -070081 * Solaris 11.3), it is blocking whereas os.urandom() should not block. */
Victor Stinnerbae2d622015-10-01 09:47:30 +020082#elif defined(HAVE_GETENTROPY) && !defined(sun)
83#define PY_GETENTROPY 1
84
Victor Stinner4d6a3d62014-12-21 01:16:38 +010085/* Fill buffer with size pseudo-random bytes generated by getentropy().
86 Return 0 on success, or raise an exception and return -1 on error.
Georg Brandl2daf6ae2012-02-20 19:54:16 +010087
Victor Stinner4bad3b62016-08-16 15:23:58 +020088 If raise is zero, don't raise an exception on error. */
Victor Stinner4d6a3d62014-12-21 01:16:38 +010089static int
Victor Stinner4bad3b62016-08-16 15:23:58 +020090py_getentropy(char *buffer, Py_ssize_t size, int raise)
Victor Stinner4d6a3d62014-12-21 01:16:38 +010091{
92 while (size > 0) {
93 Py_ssize_t len = Py_MIN(size, 256);
Victor Stinner9aa13312015-03-30 11:18:30 +020094 int res;
95
Victor Stinner4bad3b62016-08-16 15:23:58 +020096 if (raise) {
Victor Stinner9aa13312015-03-30 11:18:30 +020097 Py_BEGIN_ALLOW_THREADS
98 res = getentropy(buffer, len);
99 Py_END_ALLOW_THREADS
Victor Stinner4d6a3d62014-12-21 01:16:38 +0100100 }
Victor Stinner9aa13312015-03-30 11:18:30 +0200101 else {
102 res = getentropy(buffer, len);
Victor Stinner4bad3b62016-08-16 15:23:58 +0200103 }
104
105 if (res < 0) {
106 if (raise) {
107 PyErr_SetFromErrno(PyExc_OSError);
108 }
109 return -1;
Victor Stinner9aa13312015-03-30 11:18:30 +0200110 }
111
Victor Stinner4d6a3d62014-12-21 01:16:38 +0100112 buffer += len;
113 size -= len;
114 }
115 return 0;
116}
117
Victor Stinnerbae2d622015-10-01 09:47:30 +0200118#else
Victor Stinner59f7fb22015-03-18 14:39:33 +0100119
Victor Stinnerbae2d622015-10-01 09:47:30 +0200120#if defined(HAVE_GETRANDOM) || defined(HAVE_GETRANDOM_SYSCALL)
121#define PY_GETRANDOM 1
122
Victor Stinner6974cf22016-08-16 18:46:38 +0200123/* Call getrandom()
124 - Return 1 on success
Victor Stinner6d8bc462016-09-20 22:46:02 +0200125 - Return 0 if getrandom() syscall is not available (failed with ENOSYS or
126 EPERM) or if getrandom(GRND_NONBLOCK) failed with EAGAIN (system urandom
Victor Stinneraf597322016-09-20 22:26:18 +0200127 not initialized yet) and raise=0.
Victor Stinner6974cf22016-08-16 18:46:38 +0200128 - Raise an exception (if raise is non-zero) and return -1 on error:
129 getrandom() failed with EINTR and the Python signal handler raised an
130 exception, or getrandom() failed with a different error. */
Victor Stinner59f7fb22015-03-18 14:39:33 +0100131static int
Victor Stinnere66987e2016-09-06 16:33:52 -0700132py_getrandom(void *buffer, Py_ssize_t size, int blocking, int raise)
Victor Stinner59f7fb22015-03-18 14:39:33 +0100133{
Victor Stinnere66987e2016-09-06 16:33:52 -0700134 /* Is getrandom() supported by the running kernel? Set to 0 if getrandom()
Victor Stinner6d8bc462016-09-20 22:46:02 +0200135 failed with ENOSYS or EPERM. Need Linux kernel 3.17 or newer, or Solaris
Victor Stinneraf597322016-09-20 22:26:18 +0200136 11.3 or newer */
Victor Stinner59f7fb22015-03-18 14:39:33 +0100137 static int getrandom_works = 1;
Victor Stinnere66987e2016-09-06 16:33:52 -0700138 int flags;
Victor Stinnercfb19612016-06-08 10:16:50 +0200139 char *dest;
Victor Stinnerec721f32016-06-16 23:53:47 +0200140 long n;
Victor Stinner59f7fb22015-03-18 14:39:33 +0100141
Victor Stinner6974cf22016-08-16 18:46:38 +0200142 if (!getrandom_works) {
Victor Stinner59f7fb22015-03-18 14:39:33 +0100143 return 0;
Victor Stinner6974cf22016-08-16 18:46:38 +0200144 }
Victor Stinner59f7fb22015-03-18 14:39:33 +0100145
Victor Stinnere66987e2016-09-06 16:33:52 -0700146 flags = blocking ? 0 : GRND_NONBLOCK;
Victor Stinnercfb19612016-06-08 10:16:50 +0200147 dest = buffer;
Victor Stinner59f7fb22015-03-18 14:39:33 +0100148 while (0 < size) {
Victor Stinner9d242712016-04-12 22:28:49 +0200149#ifdef sun
150 /* Issue #26735: On Solaris, getrandom() is limited to returning up
151 to 1024 bytes */
152 n = Py_MIN(size, 1024);
153#else
Victor Stinnerec721f32016-06-16 23:53:47 +0200154 n = Py_MIN(size, LONG_MAX);
Victor Stinner9d242712016-04-12 22:28:49 +0200155#endif
Victor Stinner79b74ae2015-03-30 11:16:40 +0200156
Victor Stinner9d242712016-04-12 22:28:49 +0200157 errno = 0;
Victor Stinnerbae2d622015-10-01 09:47:30 +0200158#ifdef HAVE_GETRANDOM
159 if (raise) {
160 Py_BEGIN_ALLOW_THREADS
Victor Stinnercfb19612016-06-08 10:16:50 +0200161 n = getrandom(dest, n, flags);
Victor Stinnerbae2d622015-10-01 09:47:30 +0200162 Py_END_ALLOW_THREADS
163 }
164 else {
Victor Stinnercfb19612016-06-08 10:16:50 +0200165 n = getrandom(dest, n, flags);
Victor Stinnerbae2d622015-10-01 09:47:30 +0200166 }
167#else
168 /* On Linux, use the syscall() function because the GNU libc doesn't
Victor Stinner6974cf22016-08-16 18:46:38 +0200169 expose the Linux getrandom() syscall yet. See:
170 https://sourceware.org/bugzilla/show_bug.cgi?id=17252 */
Victor Stinner79b74ae2015-03-30 11:16:40 +0200171 if (raise) {
172 Py_BEGIN_ALLOW_THREADS
Victor Stinnercfb19612016-06-08 10:16:50 +0200173 n = syscall(SYS_getrandom, dest, n, flags);
Victor Stinner79b74ae2015-03-30 11:16:40 +0200174 Py_END_ALLOW_THREADS
175 }
176 else {
Victor Stinnercfb19612016-06-08 10:16:50 +0200177 n = syscall(SYS_getrandom, dest, n, flags);
Victor Stinner79b74ae2015-03-30 11:16:40 +0200178 }
Victor Stinnerbae2d622015-10-01 09:47:30 +0200179#endif
Victor Stinner79b74ae2015-03-30 11:16:40 +0200180
Victor Stinner59f7fb22015-03-18 14:39:33 +0100181 if (n < 0) {
Victor Stinneraf597322016-09-20 22:26:18 +0200182 /* ENOSYS: getrandom() syscall not supported by the kernel (but
Victor Stinner6d8bc462016-09-20 22:46:02 +0200183 * maybe supported by the host which built Python). EPERM:
184 * getrandom() syscall blocked by SECCOMP or something else. */
185 if (errno == ENOSYS || errno == EPERM) {
Victor Stinner59f7fb22015-03-18 14:39:33 +0100186 getrandom_works = 0;
187 return 0;
188 }
Victor Stinner6974cf22016-08-16 18:46:38 +0200189
Victor Stinnere66987e2016-09-06 16:33:52 -0700190 /* getrandom(GRND_NONBLOCK) fails with EAGAIN if the system urandom
191 is not initialiazed yet. For _PyRandom_Init(), we ignore their
192 error and fall back on reading /dev/urandom which never blocks,
193 even if the system urandom is not initialized yet. */
194 if (errno == EAGAIN && !raise && !blocking) {
Victor Stinnerdddf4842016-06-07 11:21:42 +0200195 return 0;
196 }
Victor Stinner59f7fb22015-03-18 14:39:33 +0100197
198 if (errno == EINTR) {
Victor Stinnercecdd962016-08-16 15:19:09 +0200199 if (raise) {
200 if (PyErr_CheckSignals()) {
201 return -1;
202 }
Victor Stinner59f7fb22015-03-18 14:39:33 +0100203 }
Victor Stinnercecdd962016-08-16 15:19:09 +0200204
205 /* retry getrandom() if it was interrupted by a signal */
Victor Stinner59f7fb22015-03-18 14:39:33 +0100206 continue;
207 }
208
Victor Stinner4bad3b62016-08-16 15:23:58 +0200209 if (raise) {
Victor Stinner59f7fb22015-03-18 14:39:33 +0100210 PyErr_SetFromErrno(PyExc_OSError);
Victor Stinner4bad3b62016-08-16 15:23:58 +0200211 }
Victor Stinner59f7fb22015-03-18 14:39:33 +0100212 return -1;
213 }
214
Victor Stinnercfb19612016-06-08 10:16:50 +0200215 dest += n;
Victor Stinner59f7fb22015-03-18 14:39:33 +0100216 size -= n;
217 }
218 return 1;
219}
220#endif
221
Antoine Pitroue472aea2014-04-26 14:33:03 +0200222static struct {
223 int fd;
224 dev_t st_dev;
225 ino_t st_ino;
226} urandom_cache = { -1 };
Georg Brandl2daf6ae2012-02-20 19:54:16 +0100227
Victor Stinner59f7fb22015-03-18 14:39:33 +0100228
Victor Stinnere66987e2016-09-06 16:33:52 -0700229/* Read 'size' random bytes from py_getrandom(). Fall back on reading from
Victor Stinner6974cf22016-08-16 18:46:38 +0200230 /dev/urandom if getrandom() is not available.
231
232 Return 0 on success. Raise an exception (if raise is non-zero) and return -1
233 on error. */
Victor Stinner4bad3b62016-08-16 15:23:58 +0200234static int
Victor Stinnere66987e2016-09-06 16:33:52 -0700235dev_urandom(char *buffer, Py_ssize_t size, int blocking, int raise)
Georg Brandl2daf6ae2012-02-20 19:54:16 +0100236{
237 int fd;
238 Py_ssize_t n;
Victor Stinnerbae2d622015-10-01 09:47:30 +0200239#ifdef PY_GETRANDOM
Victor Stinner59f7fb22015-03-18 14:39:33 +0100240 int res;
241#endif
Georg Brandl2daf6ae2012-02-20 19:54:16 +0100242
Victor Stinner6974cf22016-08-16 18:46:38 +0200243 assert(size > 0);
Georg Brandl2daf6ae2012-02-20 19:54:16 +0100244
Victor Stinnerbae2d622015-10-01 09:47:30 +0200245#ifdef PY_GETRANDOM
Victor Stinnere66987e2016-09-06 16:33:52 -0700246 res = py_getrandom(buffer, size, blocking, raise);
Victor Stinner6974cf22016-08-16 18:46:38 +0200247 if (res < 0) {
Victor Stinner59f7fb22015-03-18 14:39:33 +0100248 return -1;
Victor Stinner6974cf22016-08-16 18:46:38 +0200249 }
250 if (res == 1) {
Victor Stinner59f7fb22015-03-18 14:39:33 +0100251 return 0;
Victor Stinner6974cf22016-08-16 18:46:38 +0200252 }
Victor Stinner6d8bc462016-09-20 22:46:02 +0200253 /* getrandom() failed with ENOSYS or EPERM,
Victor Stinneraf597322016-09-20 22:26:18 +0200254 fall back on reading /dev/urandom */
Victor Stinner59f7fb22015-03-18 14:39:33 +0100255#endif
256
Victor Stinner6974cf22016-08-16 18:46:38 +0200257
258 if (raise) {
259 struct _Py_stat_struct st;
260
Antoine Pitroue472aea2014-04-26 14:33:03 +0200261 if (urandom_cache.fd >= 0) {
Victor Stinner6974cf22016-08-16 18:46:38 +0200262 /* Does the fd point to the same thing as before? (issue #21207) */
263 if (_Py_fstat_noraise(urandom_cache.fd, &st)
264 || st.st_dev != urandom_cache.st_dev
265 || st.st_ino != urandom_cache.st_ino) {
266 /* Something changed: forget the cached fd (but don't close it,
267 since it probably points to something important for some
268 third-party code). */
269 urandom_cache.fd = -1;
270 }
Antoine Pitrou4879a962013-08-31 00:26:02 +0200271 }
Victor Stinner6974cf22016-08-16 18:46:38 +0200272 if (urandom_cache.fd >= 0)
273 fd = urandom_cache.fd;
Antoine Pitroue472aea2014-04-26 14:33:03 +0200274 else {
Victor Stinner6974cf22016-08-16 18:46:38 +0200275 fd = _Py_open("/dev/urandom", O_RDONLY);
276 if (fd < 0) {
277 if (errno == ENOENT || errno == ENXIO ||
278 errno == ENODEV || errno == EACCES)
279 PyErr_SetString(PyExc_NotImplementedError,
280 "/dev/urandom (or equivalent) not found");
281 /* otherwise, keep the OSError exception raised by _Py_open() */
Antoine Pitroue472aea2014-04-26 14:33:03 +0200282 return -1;
283 }
Victor Stinner6974cf22016-08-16 18:46:38 +0200284 if (urandom_cache.fd >= 0) {
285 /* urandom_fd was initialized by another thread while we were
286 not holding the GIL, keep it. */
287 close(fd);
288 fd = urandom_cache.fd;
289 }
Antoine Pitroue472aea2014-04-26 14:33:03 +0200290 else {
Victor Stinner6974cf22016-08-16 18:46:38 +0200291 if (_Py_fstat(fd, &st)) {
292 close(fd);
293 return -1;
294 }
295 else {
296 urandom_cache.fd = fd;
297 urandom_cache.st_dev = st.st_dev;
298 urandom_cache.st_ino = st.st_ino;
299 }
Antoine Pitroue472aea2014-04-26 14:33:03 +0200300 }
301 }
Georg Brandl2daf6ae2012-02-20 19:54:16 +0100302
Victor Stinner6974cf22016-08-16 18:46:38 +0200303 do {
304 n = _Py_read(fd, buffer, (size_t)size);
305 if (n == -1)
306 return -1;
307 if (n == 0) {
308 PyErr_Format(PyExc_RuntimeError,
309 "Failed to read %zi bytes from /dev/urandom",
310 size);
311 return -1;
312 }
313
314 buffer += n;
315 size -= n;
316 } while (0 < size);
317 }
318 else {
319 fd = _Py_open_noraise("/dev/urandom", O_RDONLY);
320 if (fd < 0) {
Victor Stinnerc9382eb2015-03-19 23:36:33 +0100321 return -1;
322 }
323
Victor Stinner6974cf22016-08-16 18:46:38 +0200324 while (0 < size)
325 {
326 do {
327 n = read(fd, buffer, (size_t)size);
328 } while (n < 0 && errno == EINTR);
Victor Stinnerc9382eb2015-03-19 23:36:33 +0100329
Victor Stinner6974cf22016-08-16 18:46:38 +0200330 if (n <= 0) {
331 /* stop on error or if read(size) returned 0 */
Victor Stinner3ee933f2016-08-16 18:27:44 +0200332 close(fd);
Victor Stinner6974cf22016-08-16 18:46:38 +0200333 return -1;
334 }
335
336 buffer += n;
337 size -= n;
338 }
339 close(fd);
340 }
Georg Brandl2daf6ae2012-02-20 19:54:16 +0100341 return 0;
342}
Antoine Pitrou4879a962013-08-31 00:26:02 +0200343
344static void
345dev_urandom_close(void)
346{
Antoine Pitroue472aea2014-04-26 14:33:03 +0200347 if (urandom_cache.fd >= 0) {
348 close(urandom_cache.fd);
349 urandom_cache.fd = -1;
Antoine Pitrou4879a962013-08-31 00:26:02 +0200350 }
351}
352
Victor Stinnerbae2d622015-10-01 09:47:30 +0200353#endif
Georg Brandl2daf6ae2012-02-20 19:54:16 +0100354
355/* Fill buffer with pseudo-random bytes generated by a linear congruent
356 generator (LCG):
357
358 x(n+1) = (x(n) * 214013 + 2531011) % 2^32
359
360 Use bits 23..16 of x(n) to generate a byte. */
361static void
362lcg_urandom(unsigned int x0, unsigned char *buffer, size_t size)
363{
364 size_t index;
365 unsigned int x;
366
367 x = x0;
368 for (index=0; index < size; index++) {
369 x *= 214013;
370 x += 2531011;
371 /* modulo 2 ^ (8 * sizeof(int)) */
372 buffer[index] = (x >> 16) & 0xff;
373 }
374}
375
Victor Stinner4bad3b62016-08-16 15:23:58 +0200376/* If raise is zero:
Victor Stinner6974cf22016-08-16 18:46:38 +0200377 - Don't raise exceptions on error
378 - Don't call PyErr_CheckSignals() on EINTR (retry directly the interrupted
379 syscall)
380 - Don't release the GIL to call syscalls. */
Victor Stinner4bad3b62016-08-16 15:23:58 +0200381static int
Victor Stinnere66987e2016-09-06 16:33:52 -0700382pyurandom(void *buffer, Py_ssize_t size, int blocking, int raise)
Victor Stinner4bad3b62016-08-16 15:23:58 +0200383{
384 if (size < 0) {
385 if (raise) {
386 PyErr_Format(PyExc_ValueError,
387 "negative argument not allowed");
388 }
389 return -1;
390 }
391
392 if (size == 0) {
393 return 0;
394 }
395
396#ifdef MS_WINDOWS
397 return win32_urandom((unsigned char *)buffer, size, raise);
398#elif defined(PY_GETENTROPY)
399 return py_getentropy(buffer, size, raise);
400#else
Victor Stinnere66987e2016-09-06 16:33:52 -0700401 return dev_urandom(buffer, size, blocking, raise);
Victor Stinner4bad3b62016-08-16 15:23:58 +0200402#endif
403}
404
Georg Brandlc6a2c9b2013-10-06 18:43:19 +0200405/* Fill buffer with size pseudo-random bytes from the operating system random
Serhiy Storchaka56a6d852014-12-01 18:28:43 +0200406 number generator (RNG). It is suitable for most cryptographic purposes
Georg Brandlc6a2c9b2013-10-06 18:43:19 +0200407 except long living private keys for asymmetric encryption.
Georg Brandl2daf6ae2012-02-20 19:54:16 +0100408
Victor Stinnere66987e2016-09-06 16:33:52 -0700409 On Linux 3.17 and newer, the getrandom() syscall is used in blocking mode:
410 block until the system urandom entropy pool is initialized (128 bits are
411 collected by the kernel).
412
413 Return 0 on success. Raise an exception and return -1 on error. */
Georg Brandl2daf6ae2012-02-20 19:54:16 +0100414int
415_PyOS_URandom(void *buffer, Py_ssize_t size)
416{
Victor Stinnere66987e2016-09-06 16:33:52 -0700417 return pyurandom(buffer, size, 1, 1);
418}
419
420/* Fill buffer with size pseudo-random bytes from the operating system random
421 number generator (RNG). It is not suitable for cryptographic purpose.
422
423 On Linux 3.17 and newer (when getrandom() syscall is used), if the system
424 urandom is not initialized yet, the function returns "weak" entropy read
425 from /dev/urandom.
426
427 Return 0 on success. Raise an exception and return -1 on error. */
428int
429_PyOS_URandomNonblock(void *buffer, Py_ssize_t size)
430{
431 return pyurandom(buffer, size, 0, 1);
Georg Brandl2daf6ae2012-02-20 19:54:16 +0100432}
433
434void
435_PyRandom_Init(void)
436{
437 char *env;
Christian Heimes985ecdc2013-11-20 11:46:18 +0100438 unsigned char *secret = (unsigned char *)&_Py_HashSecret.uc;
Benjamin Peterson69e97272012-02-21 11:08:50 -0500439 Py_ssize_t secret_size = sizeof(_Py_HashSecret_t);
Serhiy Storchakafad85aa2015-11-07 15:42:38 +0200440 Py_BUILD_ASSERT(sizeof(_Py_HashSecret_t) == sizeof(_Py_HashSecret.uc));
Georg Brandl2daf6ae2012-02-20 19:54:16 +0100441
Benjamin Peterson69e97272012-02-21 11:08:50 -0500442 if (_Py_HashSecret_Initialized)
Georg Brandl2daf6ae2012-02-20 19:54:16 +0100443 return;
Benjamin Peterson69e97272012-02-21 11:08:50 -0500444 _Py_HashSecret_Initialized = 1;
Georg Brandl2daf6ae2012-02-20 19:54:16 +0100445
446 /*
Georg Brandl2daf6ae2012-02-20 19:54:16 +0100447 Hash randomization is enabled. Generate a per-process secret,
448 using PYTHONHASHSEED if provided.
449 */
450
451 env = Py_GETENV("PYTHONHASHSEED");
Georg Brandl12897d72012-02-20 23:49:29 +0100452 if (env && *env != '\0' && strcmp(env, "random") != 0) {
Georg Brandl2daf6ae2012-02-20 19:54:16 +0100453 char *endptr = env;
454 unsigned long seed;
455 seed = strtoul(env, &endptr, 10);
456 if (*endptr != '\0'
457 || seed > 4294967295UL
458 || (errno == ERANGE && seed == ULONG_MAX))
459 {
460 Py_FatalError("PYTHONHASHSEED must be \"random\" or an integer "
461 "in range [0; 4294967295]");
462 }
463 if (seed == 0) {
464 /* disable the randomized hash */
465 memset(secret, 0, secret_size);
466 }
467 else {
Christian Heimes985ecdc2013-11-20 11:46:18 +0100468 lcg_urandom(seed, secret, secret_size);
Georg Brandl2daf6ae2012-02-20 19:54:16 +0100469 }
470 }
471 else {
Victor Stinner4bad3b62016-08-16 15:23:58 +0200472 int res;
473
474 /* _PyRandom_Init() is called very early in the Python initialization
Victor Stinnere66987e2016-09-06 16:33:52 -0700475 and so exceptions cannot be used (use raise=0).
476
477 _PyRandom_Init() must not block Python initialization: call
478 pyurandom() is non-blocking mode (blocking=0): see the PEP 524. */
479 res = pyurandom(secret, secret_size, 0, 0);
Victor Stinner4bad3b62016-08-16 15:23:58 +0200480 if (res < 0) {
481 Py_FatalError("failed to get random numbers to initialize Python");
482 }
Georg Brandl2daf6ae2012-02-20 19:54:16 +0100483 }
484}
Antoine Pitrou4879a962013-08-31 00:26:02 +0200485
486void
487_PyRandom_Fini(void)
488{
Victor Stinnerd50c3f32014-05-02 22:06:44 +0200489#ifdef MS_WINDOWS
490 if (hCryptProv) {
Tim Goldenb8ac3e12014-05-06 13:29:45 +0100491 CryptReleaseContext(hCryptProv, 0);
Victor Stinnerd50c3f32014-05-02 22:06:44 +0200492 hCryptProv = 0;
493 }
Victor Stinnerbae2d622015-10-01 09:47:30 +0200494#elif defined(PY_GETENTROPY)
Victor Stinner4d6a3d62014-12-21 01:16:38 +0100495 /* nothing to clean */
Victor Stinnerd50c3f32014-05-02 22:06:44 +0200496#else
Antoine Pitrou4879a962013-08-31 00:26:02 +0200497 dev_urandom_close();
498#endif
499}