1 #include "Python.h"
2 #ifdef MS_WINDOWS
3 # include <windows.h>
4 /* All sample MSDN wincrypt programs include the header below. It is at least
5 * required with Min GW. */
6 # include <wincrypt.h>
7 #else
8 # include <fcntl.h>
9 # ifdef HAVE_SYS_STAT_H
10 # include <sys/stat.h>
11 # endif
12 # ifdef HAVE_LINUX_RANDOM_H
13 # include <linux/random.h>
14 # endif
15 # if defined(HAVE_SYS_RANDOM_H) && (defined(HAVE_GETRANDOM) || defined(HAVE_GETENTROPY))
16 # include <sys/random.h>
17 # endif
18 # if !defined(HAVE_GETRANDOM) && defined(HAVE_GETRANDOM_SYSCALL)
19 # include <sys/syscall.h>
20 # endif
21 #endif
22
23 #ifdef _Py_MEMORY_SANITIZER
24 # include <sanitizer/msan_interface.h>
25 #endif
26
27 #ifdef Py_DEBUG
28 int _Py_HashSecret_Initialized = 0;
29 #else
30 static int _Py_HashSecret_Initialized = 0;
31 #endif
32
33 #ifdef MS_WINDOWS
34 static HCRYPTPROV hCryptProv = 0;
35
36 static int
win32_urandom_init(int raise)37 win32_urandom_init(int raise)
38 {
39 /* Acquire context */
40 if (!CryptAcquireContext(&hCryptProv, NULL, NULL,
41 PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
42 goto error;
43
44 return 0;
45
46 error:
47 if (raise) {
48 PyErr_SetFromWindowsErr(0);
49 }
50 return -1;
51 }
52
53 /* Fill buffer with size pseudo-random bytes generated by the Windows CryptoGen
54 API. Return 0 on success, or raise an exception and return -1 on error. */
55 static int
win32_urandom(unsigned char * buffer,Py_ssize_t size,int raise)56 win32_urandom(unsigned char *buffer, Py_ssize_t size, int raise)
57 {
58 Py_ssize_t chunk;
59
60 if (hCryptProv == 0)
61 {
62 if (win32_urandom_init(raise) == -1) {
63 return -1;
64 }
65 }
66
67 while (size > 0)
68 {
69 chunk = size > INT_MAX ? INT_MAX : size;
70 if (!CryptGenRandom(hCryptProv, (DWORD)chunk, buffer))
71 {
72 /* CryptGenRandom() failed */
73 if (raise) {
74 PyErr_SetFromWindowsErr(0);
75 }
76 return -1;
77 }
78 buffer += chunk;
79 size -= chunk;
80 }
81 return 0;
82 }
83
84 #else /* !MS_WINDOWS */
85
86 #if defined(HAVE_GETRANDOM) || defined(HAVE_GETRANDOM_SYSCALL)
87 #define PY_GETRANDOM 1
88
89 /* Call getrandom() to get random bytes:
90
91 - Return 1 on success
92 - Return 0 if getrandom() is not available (failed with ENOSYS or EPERM),
93 or if getrandom(GRND_NONBLOCK) failed with EAGAIN (system urandom not
94 initialized yet) and raise=0.
95 - Raise an exception (if raise is non-zero) and return -1 on error:
96 if getrandom() failed with EINTR, raise is non-zero and the Python signal
97 handler raised an exception, or if getrandom() failed with a different
98 error.
99
100 getrandom() is retried if it failed with EINTR: interrupted by a signal. */
101 static int
py_getrandom(void * buffer,Py_ssize_t size,int blocking,int raise)102 py_getrandom(void *buffer, Py_ssize_t size, int blocking, int raise)
103 {
104 /* Is getrandom() supported by the running kernel? Set to 0 if getrandom()
105 failed with ENOSYS or EPERM. Need Linux kernel 3.17 or newer, or Solaris
106 11.3 or newer */
107 static int getrandom_works = 1;
108 int flags;
109 char *dest;
110 long n;
111
112 if (!getrandom_works) {
113 return 0;
114 }
115
116 flags = blocking ? 0 : GRND_NONBLOCK;
117 dest = buffer;
118 while (0 < size) {
119 #if defined(__sun) && defined(__SVR4)
120 /* Issue #26735: On Solaris, getrandom() is limited to returning up
121 to 1024 bytes. Call it multiple times if more bytes are
122 requested. */
123 n = Py_MIN(size, 1024);
124 #else
125 n = Py_MIN(size, LONG_MAX);
126 #endif
127
128 errno = 0;
129 #ifdef HAVE_GETRANDOM
130 if (raise) {
131 Py_BEGIN_ALLOW_THREADS
132 n = getrandom(dest, n, flags);
133 Py_END_ALLOW_THREADS
134 }
135 else {
136 n = getrandom(dest, n, flags);
137 }
138 #else
139 /* On Linux, use the syscall() function because the GNU libc doesn't
140 expose the Linux getrandom() syscall yet. See:
141 https://sourceware.org/bugzilla/show_bug.cgi?id=17252 */
142 if (raise) {
143 Py_BEGIN_ALLOW_THREADS
144 n = syscall(SYS_getrandom, dest, n, flags);
145 Py_END_ALLOW_THREADS
146 }
147 else {
148 n = syscall(SYS_getrandom, dest, n, flags);
149 }
150 # ifdef _Py_MEMORY_SANITIZER
151 if (n > 0) {
152 __msan_unpoison(dest, n);
153 }
154 # endif
155 #endif
156
157 if (n < 0) {
158 /* ENOSYS: the syscall is not supported by the kernel.
159 EPERM: the syscall is blocked by a security policy (ex: SECCOMP)
160 or something else. */
161 if (errno == ENOSYS || errno == EPERM) {
162 getrandom_works = 0;
163 return 0;
164 }
165
166 /* getrandom(GRND_NONBLOCK) fails with EAGAIN if the system urandom
167 is not initialiazed yet. For _PyRandom_Init(), we ignore the
168 error and fall back on reading /dev/urandom which never blocks,
169 even if the system urandom is not initialized yet:
170 see the PEP 524. */
171 if (errno == EAGAIN && !raise && !blocking) {
172 return 0;
173 }
174
175 if (errno == EINTR) {
176 if (raise) {
177 if (PyErr_CheckSignals()) {
178 return -1;
179 }
180 }
181
182 /* retry getrandom() if it was interrupted by a signal */
183 continue;
184 }
185
186 if (raise) {
187 PyErr_SetFromErrno(PyExc_OSError);
188 }
189 return -1;
190 }
191
192 dest += n;
193 size -= n;
194 }
195 return 1;
196 }
197
198 #elif defined(HAVE_GETENTROPY)
199 #define PY_GETENTROPY 1
200
201 /* Fill buffer with size pseudo-random bytes generated by getentropy():
202
203 - Return 1 on success
204 - Return 0 if getentropy() syscall is not available (failed with ENOSYS or
205 EPERM).
206 - Raise an exception (if raise is non-zero) and return -1 on error:
207 if getentropy() failed with EINTR, raise is non-zero and the Python signal
208 handler raised an exception, or if getentropy() failed with a different
209 error.
210
211 getentropy() is retried if it failed with EINTR: interrupted by a signal. */
212 static int
py_getentropy(char * buffer,Py_ssize_t size,int raise)213 py_getentropy(char *buffer, Py_ssize_t size, int raise)
214 {
215 /* Is getentropy() supported by the running kernel? Set to 0 if
216 getentropy() failed with ENOSYS or EPERM. */
217 static int getentropy_works = 1;
218
219 if (!getentropy_works) {
220 return 0;
221 }
222
223 while (size > 0) {
224 /* getentropy() is limited to returning up to 256 bytes. Call it
225 multiple times if more bytes are requested. */
226 Py_ssize_t len = Py_MIN(size, 256);
227 int res;
228
229 if (raise) {
230 Py_BEGIN_ALLOW_THREADS
231 res = getentropy(buffer, len);
232 Py_END_ALLOW_THREADS
233 }
234 else {
235 res = getentropy(buffer, len);
236 }
237
238 if (res < 0) {
239 /* ENOSYS: the syscall is not supported by the running kernel.
240 EPERM: the syscall is blocked by a security policy (ex: SECCOMP)
241 or something else. */
242 if (errno == ENOSYS || errno == EPERM) {
243 getentropy_works = 0;
244 return 0;
245 }
246
247 if (errno == EINTR) {
248 if (raise) {
249 if (PyErr_CheckSignals()) {
250 return -1;
251 }
252 }
253
254 /* retry getentropy() if it was interrupted by a signal */
255 continue;
256 }
257
258 if (raise) {
259 PyErr_SetFromErrno(PyExc_OSError);
260 }
261 return -1;
262 }
263
264 buffer += len;
265 size -= len;
266 }
267 return 1;
268 }
269 #endif /* defined(HAVE_GETENTROPY) && !(defined(__sun) && defined(__SVR4)) */
270
271
272 static struct {
273 int fd;
274 dev_t st_dev;
275 ino_t st_ino;
276 } urandom_cache = { -1 };
277
278 /* Read random bytes from the /dev/urandom device:
279
280 - Return 0 on success
281 - Raise an exception (if raise is non-zero) and return -1 on error
282
283 Possible causes of errors:
284
285 - open() failed with ENOENT, ENXIO, ENODEV, EACCES: the /dev/urandom device
286 was not found. For example, it was removed manually or not exposed in a
287 chroot or container.
288 - open() failed with a different error
289 - fstat() failed
290 - read() failed or returned 0
291
292 read() is retried if it failed with EINTR: interrupted by a signal.
293
294 The file descriptor of the device is kept open between calls to avoid using
295 many file descriptors when run in parallel from multiple threads:
296 see the issue #18756.
297
298 st_dev and st_ino fields of the file descriptor (from fstat()) are cached to
299 check if the file descriptor was replaced by a different file (which is
300 likely a bug in the application): see the issue #21207.
301
302 If the file descriptor was closed or replaced, open a new file descriptor
303 but don't close the old file descriptor: it probably points to something
304 important for some third-party code. */
305 static int
dev_urandom(char * buffer,Py_ssize_t size,int raise)306 dev_urandom(char *buffer, Py_ssize_t size, int raise)
307 {
308 int fd;
309 Py_ssize_t n;
310
311 if (raise) {
312 struct _Py_stat_struct st;
313 int fstat_result;
314
315 if (urandom_cache.fd >= 0) {
316 Py_BEGIN_ALLOW_THREADS
317 fstat_result = _Py_fstat_noraise(urandom_cache.fd, &st);
318 Py_END_ALLOW_THREADS
319
320 /* Does the fd point to the same thing as before? (issue #21207) */
321 if (fstat_result
322 || st.st_dev != urandom_cache.st_dev
323 || st.st_ino != urandom_cache.st_ino) {
324 /* Something changed: forget the cached fd (but don't close it,
325 since it probably points to something important for some
326 third-party code). */
327 urandom_cache.fd = -1;
328 }
329 }
330 if (urandom_cache.fd >= 0)
331 fd = urandom_cache.fd;
332 else {
333 fd = _Py_open("/dev/urandom", O_RDONLY);
334 if (fd < 0) {
335 if (errno == ENOENT || errno == ENXIO ||
336 errno == ENODEV || errno == EACCES) {
337 PyErr_SetString(PyExc_NotImplementedError,
338 "/dev/urandom (or equivalent) not found");
339 }
340 /* otherwise, keep the OSError exception raised by _Py_open() */
341 return -1;
342 }
343 if (urandom_cache.fd >= 0) {
344 /* urandom_fd was initialized by another thread while we were
345 not holding the GIL, keep it. */
346 close(fd);
347 fd = urandom_cache.fd;
348 }
349 else {
350 if (_Py_fstat(fd, &st)) {
351 close(fd);
352 return -1;
353 }
354 else {
355 urandom_cache.fd = fd;
356 urandom_cache.st_dev = st.st_dev;
357 urandom_cache.st_ino = st.st_ino;
358 }
359 }
360 }
361
362 do {
363 n = _Py_read(fd, buffer, (size_t)size);
364 if (n == -1)
365 return -1;
366 if (n == 0) {
367 PyErr_Format(PyExc_RuntimeError,
368 "Failed to read %zi bytes from /dev/urandom",
369 size);
370 return -1;
371 }
372
373 buffer += n;
374 size -= n;
375 } while (0 < size);
376 }
377 else {
378 fd = _Py_open_noraise("/dev/urandom", O_RDONLY);
379 if (fd < 0) {
380 return -1;
381 }
382
383 while (0 < size)
384 {
385 do {
386 n = read(fd, buffer, (size_t)size);
387 } while (n < 0 && errno == EINTR);
388
389 if (n <= 0) {
390 /* stop on error or if read(size) returned 0 */
391 close(fd);
392 return -1;
393 }
394
395 buffer += n;
396 size -= n;
397 }
398 close(fd);
399 }
400 return 0;
401 }
402
403 static void
dev_urandom_close(void)404 dev_urandom_close(void)
405 {
406 if (urandom_cache.fd >= 0) {
407 close(urandom_cache.fd);
408 urandom_cache.fd = -1;
409 }
410 }
411 #endif /* !MS_WINDOWS */
412
413
414 /* Fill buffer with pseudo-random bytes generated by a linear congruent
415 generator (LCG):
416
417 x(n+1) = (x(n) * 214013 + 2531011) % 2^32
418
419 Use bits 23..16 of x(n) to generate a byte. */
420 static void
lcg_urandom(unsigned int x0,unsigned char * buffer,size_t size)421 lcg_urandom(unsigned int x0, unsigned char *buffer, size_t size)
422 {
423 size_t index;
424 unsigned int x;
425
426 x = x0;
427 for (index=0; index < size; index++) {
428 x *= 214013;
429 x += 2531011;
430 /* modulo 2 ^ (8 * sizeof(int)) */
431 buffer[index] = (x >> 16) & 0xff;
432 }
433 }
434
435 /* Read random bytes:
436
437 - Return 0 on success
438 - Raise an exception (if raise is non-zero) and return -1 on error
439
440 Used sources of entropy ordered by preference, preferred source first:
441
442 - CryptGenRandom() on Windows
443 - getrandom() function (ex: Linux and Solaris): call py_getrandom()
444 - getentropy() function (ex: OpenBSD): call py_getentropy()
445 - /dev/urandom device
446
447 Read from the /dev/urandom device if getrandom() or getentropy() function
448 is not available or does not work.
449
450 Prefer getrandom() over getentropy() because getrandom() supports blocking
451 and non-blocking mode: see the PEP 524. Python requires non-blocking RNG at
452 startup to initialize its hash secret, but os.urandom() must block until the
453 system urandom is initialized (at least on Linux 3.17 and newer).
454
455 Prefer getrandom() and getentropy() over reading directly /dev/urandom
456 because these functions don't need file descriptors and so avoid ENFILE or
457 EMFILE errors (too many open files): see the issue #18756.
458
459 Only the getrandom() function supports non-blocking mode.
460
461 Only use RNG running in the kernel. They are more secure because it is
462 harder to get the internal state of a RNG running in the kernel land than a
463 RNG running in the user land. The kernel has a direct access to the hardware
464 and has access to hardware RNG, they are used as entropy sources.
465
466 Note: the OpenSSL RAND_pseudo_bytes() function does not automatically reseed
467 its RNG on fork(), two child processes (with the same pid) generate the same
468 random numbers: see issue #18747. Kernel RNGs don't have this issue,
469 they have access to good quality entropy sources.
470
471 If raise is zero:
472
473 - Don't raise an exception on error
474 - Don't call the Python signal handler (don't call PyErr_CheckSignals()) if
475 a function fails with EINTR: retry directly the interrupted function
476 - Don't release the GIL to call functions.
477 */
478 static int
pyurandom(void * buffer,Py_ssize_t size,int blocking,int raise)479 pyurandom(void *buffer, Py_ssize_t size, int blocking, int raise)
480 {
481 #if defined(PY_GETRANDOM) || defined(PY_GETENTROPY)
482 int res;
483 #endif
484
485 if (size < 0) {
486 if (raise) {
487 PyErr_Format(PyExc_ValueError,
488 "negative argument not allowed");
489 }
490 return -1;
491 }
492
493 if (size == 0) {
494 return 0;
495 }
496
497 #ifdef MS_WINDOWS
498 return win32_urandom((unsigned char *)buffer, size, raise);
499 #else
500
501 #if defined(PY_GETRANDOM) || defined(PY_GETENTROPY)
502 #ifdef PY_GETRANDOM
503 res = py_getrandom(buffer, size, blocking, raise);
504 #else
505 res = py_getentropy(buffer, size, raise);
506 #endif
507 if (res < 0) {
508 return -1;
509 }
510 if (res == 1) {
511 return 0;
512 }
513 /* getrandom() or getentropy() function is not available: failed with
514 ENOSYS or EPERM. Fall back on reading from /dev/urandom. */
515 #endif
516
517 return dev_urandom(buffer, size, raise);
518 #endif
519 }
520
521 /* Fill buffer with size pseudo-random bytes from the operating system random
522 number generator (RNG). It is suitable for most cryptographic purposes
523 except long living private keys for asymmetric encryption.
524
525 On Linux 3.17 and newer, the getrandom() syscall is used in blocking mode:
526 block until the system urandom entropy pool is initialized (128 bits are
527 collected by the kernel).
528
529 Return 0 on success. Raise an exception and return -1 on error. */
530 int
_PyOS_URandom(void * buffer,Py_ssize_t size)531 _PyOS_URandom(void *buffer, Py_ssize_t size)
532 {
533 return pyurandom(buffer, size, 1, 1);
534 }
535
536 /* Fill buffer with size pseudo-random bytes from the operating system random
537 number generator (RNG). It is not suitable for cryptographic purpose.
538
539 On Linux 3.17 and newer (when getrandom() syscall is used), if the system
540 urandom is not initialized yet, the function returns "weak" entropy read
541 from /dev/urandom.
542
543 Return 0 on success. Raise an exception and return -1 on error. */
544 int
_PyOS_URandomNonblock(void * buffer,Py_ssize_t size)545 _PyOS_URandomNonblock(void *buffer, Py_ssize_t size)
546 {
547 return pyurandom(buffer, size, 0, 1);
548 }
549
550 int
_Py_ReadHashSeed(const char * seed_text,int * use_hash_seed,unsigned long * hash_seed)551 _Py_ReadHashSeed(const char *seed_text,
552 int *use_hash_seed,
553 unsigned long *hash_seed)
554 {
555 Py_BUILD_ASSERT(sizeof(_Py_HashSecret_t) == sizeof(_Py_HashSecret.uc));
556 /* Convert a text seed to a numeric one */
557 if (seed_text && *seed_text != '\0' && strcmp(seed_text, "random") != 0) {
558 const char *endptr = seed_text;
559 unsigned long seed;
560 seed = strtoul(seed_text, (char **)&endptr, 10);
561 if (*endptr != '\0'
562 || seed > 4294967295UL
563 || (errno == ERANGE && seed == ULONG_MAX))
564 {
565 return -1;
566 }
567 /* Use a specific hash */
568 *use_hash_seed = 1;
569 *hash_seed = seed;
570 }
571 else {
572 /* Use a random hash */
573 *use_hash_seed = 0;
574 *hash_seed = 0;
575 }
576 return 0;
577 }
578
579
580 _PyInitError
_Py_HashRandomization_Init(const _PyCoreConfig * config)581 _Py_HashRandomization_Init(const _PyCoreConfig *config)
582 {
583 void *secret = &_Py_HashSecret;
584 Py_ssize_t secret_size = sizeof(_Py_HashSecret_t);
585
586 if (_Py_HashSecret_Initialized) {
587 return _Py_INIT_OK();
588 }
589 _Py_HashSecret_Initialized = 1;
590
591 if (config->use_hash_seed) {
592 if (config->hash_seed == 0) {
593 /* disable the randomized hash */
594 memset(secret, 0, secret_size);
595 }
596 else {
597 /* use the specified hash seed */
598 lcg_urandom(config->hash_seed, secret, secret_size);
599 }
600 }
601 else {
602 /* use a random hash seed */
603 int res;
604
605 /* _PyRandom_Init() is called very early in the Python initialization
606 and so exceptions cannot be used (use raise=0).
607
608 _PyRandom_Init() must not block Python initialization: call
609 pyurandom() is non-blocking mode (blocking=0): see the PEP 524. */
610 res = pyurandom(secret, secret_size, 0, 0);
611 if (res < 0) {
612 return _Py_INIT_USER_ERR("failed to get random numbers "
613 "to initialize Python");
614 }
615 }
616 return _Py_INIT_OK();
617 }
618
619
620 void
_Py_HashRandomization_Fini(void)621 _Py_HashRandomization_Fini(void)
622 {
623 #ifdef MS_WINDOWS
624 if (hCryptProv) {
625 CryptReleaseContext(hCryptProv, 0);
626 hCryptProv = 0;
627 }
628 #else
629 dev_urandom_close();
630 #endif
631 }
632