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