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