|
|
6bb1189 |
diff -r ee1390c9b585 Python/random.c
|
|
|
6bb1189 |
--- a/Python/random.c Wed Jan 04 12:02:30 2017 +0100
|
|
|
6bb1189 |
+++ b/Python/random.c Wed Jan 04 18:32:21 2017 +0100
|
|
|
6bb1189 |
@@ -77,45 +77,8 @@ win32_urandom(unsigned char *buffer, Py_
|
|
|
6bb1189 |
return 0;
|
|
|
6bb1189 |
}
|
|
|
6bb1189 |
|
|
|
6bb1189 |
-/* Issue #25003: Don't use getentropy() on Solaris (available since
|
|
|
6bb1189 |
- * Solaris 11.3), it is blocking whereas os.urandom() should not block. */
|
|
|
6bb1189 |
-#elif defined(HAVE_GETENTROPY) && !defined(sun)
|
|
|
6bb1189 |
-#define PY_GETENTROPY 1
|
|
|
6bb1189 |
-
|
|
|
6bb1189 |
-/* Fill buffer with size pseudo-random bytes generated by getentropy().
|
|
|
6bb1189 |
- Return 0 on success, or raise an exception and return -1 on error.
|
|
|
6bb1189 |
-
|
|
|
6bb1189 |
- If raise is zero, don't raise an exception on error. */
|
|
|
6bb1189 |
-static int
|
|
|
6bb1189 |
-py_getentropy(char *buffer, Py_ssize_t size, int raise)
|
|
|
6bb1189 |
-{
|
|
|
6bb1189 |
- while (size > 0) {
|
|
|
6bb1189 |
- Py_ssize_t len = Py_MIN(size, 256);
|
|
|
6bb1189 |
- int res;
|
|
|
6bb1189 |
+#else /* !MS_WINDOWS */
|
|
|
6bb1189 |
|
|
|
6bb1189 |
- if (raise) {
|
|
|
6bb1189 |
- Py_BEGIN_ALLOW_THREADS
|
|
|
6bb1189 |
- res = getentropy(buffer, len);
|
|
|
6bb1189 |
- Py_END_ALLOW_THREADS
|
|
|
6bb1189 |
- }
|
|
|
6bb1189 |
- else {
|
|
|
6bb1189 |
- res = getentropy(buffer, len);
|
|
|
6bb1189 |
- }
|
|
|
6bb1189 |
-
|
|
|
6bb1189 |
- if (res < 0) {
|
|
|
6bb1189 |
- if (raise) {
|
|
|
6bb1189 |
- PyErr_SetFromErrno(PyExc_OSError);
|
|
|
6bb1189 |
- }
|
|
|
6bb1189 |
- return -1;
|
|
|
6bb1189 |
- }
|
|
|
6bb1189 |
-
|
|
|
6bb1189 |
- buffer += len;
|
|
|
6bb1189 |
- size -= len;
|
|
|
6bb1189 |
- }
|
|
|
6bb1189 |
- return 0;
|
|
|
6bb1189 |
-}
|
|
|
6bb1189 |
-
|
|
|
6bb1189 |
-#else
|
|
|
6bb1189 |
|
|
|
6bb1189 |
#if defined(HAVE_GETRANDOM) || defined(HAVE_GETRANDOM_SYSCALL)
|
|
|
6bb1189 |
#define PY_GETRANDOM 1
|
|
|
6bb1189 |
@@ -217,6 +180,59 @@ py_getrandom(void *buffer, Py_ssize_t si
|
|
|
6bb1189 |
}
|
|
|
6bb1189 |
return 1;
|
|
|
6bb1189 |
}
|
|
|
6bb1189 |
+
|
|
|
6bb1189 |
+/* Issue #25003: Don't use getentropy() on Solaris (available since
|
|
|
6bb1189 |
+ * Solaris 11.3), it is blocking whereas os.urandom() should not block. */
|
|
|
6bb1189 |
+#elif defined(HAVE_GETENTROPY) && !defined(sun)
|
|
|
6bb1189 |
+#define PY_GETENTROPY 1
|
|
|
6bb1189 |
+
|
|
|
6bb1189 |
+/* Fill buffer with size pseudo-random bytes generated by getentropy().
|
|
|
6bb1189 |
+ Return 1 on success, or raise an exception and return -1 on error.
|
|
|
6bb1189 |
+
|
|
|
6bb1189 |
+ If raise is zero, don't raise an exception on error. */
|
|
|
6bb1189 |
+static int
|
|
|
6bb1189 |
+py_getentropy(char *buffer, Py_ssize_t size, int raise)
|
|
|
6bb1189 |
+{
|
|
|
6bb1189 |
+ /* Is getentropy() supported by the running kernel? Set to 0 if
|
|
|
6bb1189 |
+ getentropy() failed with ENOSYS. */
|
|
|
6bb1189 |
+ static int getentropy_works = 1;
|
|
|
6bb1189 |
+
|
|
|
6bb1189 |
+ if (!getentropy_works) {
|
|
|
6bb1189 |
+ return 0;
|
|
|
6bb1189 |
+ }
|
|
|
6bb1189 |
+
|
|
|
6bb1189 |
+ while (size > 0) {
|
|
|
6bb1189 |
+ Py_ssize_t len = Py_MIN(size, 256);
|
|
|
6bb1189 |
+ int res;
|
|
|
6bb1189 |
+
|
|
|
6bb1189 |
+ if (raise) {
|
|
|
6bb1189 |
+ Py_BEGIN_ALLOW_THREADS
|
|
|
6bb1189 |
+ res = getentropy(buffer, len);
|
|
|
6bb1189 |
+ Py_END_ALLOW_THREADS
|
|
|
6bb1189 |
+ }
|
|
|
6bb1189 |
+ else {
|
|
|
6bb1189 |
+ res = getentropy(buffer, len);
|
|
|
6bb1189 |
+ }
|
|
|
6bb1189 |
+
|
|
|
6bb1189 |
+ if (res < 0) {
|
|
|
6bb1189 |
+ /* ENOSYS: the inner syscall is not supported by the running
|
|
|
6bb1189 |
+ kernel. */
|
|
|
6bb1189 |
+ if (errno == ENOSYS) {
|
|
|
6bb1189 |
+ getentropy_works = 0;
|
|
|
6bb1189 |
+ return 0;
|
|
|
6bb1189 |
+ }
|
|
|
6bb1189 |
+
|
|
|
6bb1189 |
+ if (raise) {
|
|
|
6bb1189 |
+ PyErr_SetFromErrno(PyExc_OSError);
|
|
|
6bb1189 |
+ }
|
|
|
6bb1189 |
+ return -1;
|
|
|
6bb1189 |
+ }
|
|
|
6bb1189 |
+
|
|
|
6bb1189 |
+ buffer += len;
|
|
|
6bb1189 |
+ size -= len;
|
|
|
6bb1189 |
+ }
|
|
|
6bb1189 |
+ return 1;
|
|
|
6bb1189 |
+}
|
|
|
6bb1189 |
#endif
|
|
|
6bb1189 |
|
|
|
6bb1189 |
static struct {
|
|
|
6bb1189 |
@@ -236,7 +252,7 @@ dev_urandom(char *buffer, Py_ssize_t siz
|
|
|
6bb1189 |
{
|
|
|
6bb1189 |
int fd;
|
|
|
6bb1189 |
Py_ssize_t n;
|
|
|
6bb1189 |
-#ifdef PY_GETRANDOM
|
|
|
6bb1189 |
+#if defined(PY_GETRANDOM) || defined(PY_GETENTROPY)
|
|
|
6bb1189 |
int res;
|
|
|
6bb1189 |
#endif
|
|
|
6bb1189 |
|
|
|
6bb1189 |
@@ -244,17 +260,20 @@ dev_urandom(char *buffer, Py_ssize_t siz
|
|
|
6bb1189 |
|
|
|
6bb1189 |
#ifdef PY_GETRANDOM
|
|
|
6bb1189 |
res = py_getrandom(buffer, size, blocking, raise);
|
|
|
6bb1189 |
+#elif defined(PY_GETENTROPY)
|
|
|
6bb1189 |
+ res = py_getentropy(buffer, size, raise);
|
|
|
6bb1189 |
+#endif
|
|
|
6bb1189 |
+#if defined(PY_GETRANDOM) || defined(PY_GETENTROPY)
|
|
|
6bb1189 |
if (res < 0) {
|
|
|
6bb1189 |
return -1;
|
|
|
6bb1189 |
}
|
|
|
6bb1189 |
if (res == 1) {
|
|
|
6bb1189 |
return 0;
|
|
|
6bb1189 |
}
|
|
|
6bb1189 |
- /* getrandom() failed with ENOSYS or EPERM,
|
|
|
6bb1189 |
- fall back on reading /dev/urandom */
|
|
|
6bb1189 |
+ /* function failed with ENOSYS or EPERM, fall back on reading
|
|
|
6bb1189 |
+ from /dev/urandom */
|
|
|
6bb1189 |
#endif
|
|
|
6bb1189 |
|
|
|
6bb1189 |
-
|
|
|
6bb1189 |
if (raise) {
|
|
|
6bb1189 |
struct _Py_stat_struct st;
|
|
|
6bb1189 |
|
|
|
6bb1189 |
@@ -349,8 +368,8 @@ dev_urandom_close(void)
|
|
|
6bb1189 |
urandom_cache.fd = -1;
|
|
|
6bb1189 |
}
|
|
|
6bb1189 |
}
|
|
|
6bb1189 |
+#endif /* !MS_WINDOWS */
|
|
|
6bb1189 |
|
|
|
6bb1189 |
-#endif
|
|
|
6bb1189 |
|
|
|
6bb1189 |
/* Fill buffer with pseudo-random bytes generated by a linear congruent
|
|
|
6bb1189 |
generator (LCG):
|
|
|
6bb1189 |
@@ -395,8 +414,6 @@ pyurandom(void *buffer, Py_ssize_t size,
|
|
|
6bb1189 |
|
|
|
6bb1189 |
#ifdef MS_WINDOWS
|
|
|
6bb1189 |
return win32_urandom((unsigned char *)buffer, size, raise);
|
|
|
6bb1189 |
-#elif defined(PY_GETENTROPY)
|
|
|
6bb1189 |
- return py_getentropy(buffer, size, raise);
|
|
|
6bb1189 |
#else
|
|
|
6bb1189 |
return dev_urandom(buffer, size, blocking, raise);
|
|
|
6bb1189 |
#endif
|
|
|
6bb1189 |
@@ -491,8 +508,6 @@ void
|
|
|
6bb1189 |
CryptReleaseContext(hCryptProv, 0);
|
|
|
6bb1189 |
hCryptProv = 0;
|
|
|
6bb1189 |
}
|
|
|
6bb1189 |
-#elif defined(PY_GETENTROPY)
|
|
|
6bb1189 |
- /* nothing to clean */
|
|
|
6bb1189 |
#else
|
|
|
6bb1189 |
dev_urandom_close();
|
|
|
6bb1189 |
#endif
|