Issue #29157: dev_urandom() now calls py_getentropy()

Prepare the fallback to support getentropy() failure and falls back on reading
from /dev/urandom.
This commit is contained in:
Victor Stinner 2017-01-06 11:16:20 +01:00
parent 1459ca64fc
commit dcdb60e4b3

View file

@ -77,13 +77,15 @@ win32_urandom(unsigned char *buffer, Py_ssize_t size, int raise)
return 0; return 0;
} }
#else /* !MS_WINDOWS */
/* Issue #25003: Don't use getentropy() on Solaris (available since /* Issue #25003: Don't use getentropy() on Solaris (available since
* Solaris 11.3), it is blocking whereas os.urandom() should not block. */ * Solaris 11.3), it is blocking whereas os.urandom() should not block. */
#elif defined(HAVE_GETENTROPY) && !defined(sun) #if defined(HAVE_GETENTROPY) && !defined(sun)
#define PY_GETENTROPY 1 #define PY_GETENTROPY 1
/* Fill buffer with size pseudo-random bytes generated by getentropy(). /* Fill buffer with size pseudo-random bytes generated by getentropy().
Return 0 on success, or raise an exception and return -1 on error. Return 1 on success, or raise an exception and return -1 on error.
If raise is zero, don't raise an exception on error. */ If raise is zero, don't raise an exception on error. */
static int static int
@ -112,12 +114,10 @@ py_getentropy(char *buffer, Py_ssize_t size, int raise)
buffer += len; buffer += len;
size -= len; size -= len;
} }
return 0; return 1;
} }
#else #elif defined(HAVE_GETRANDOM) || defined(HAVE_GETRANDOM_SYSCALL)
#if defined(HAVE_GETRANDOM) || defined(HAVE_GETRANDOM_SYSCALL)
#define PY_GETRANDOM 1 #define PY_GETRANDOM 1
/* Call getrandom() /* Call getrandom()
@ -217,7 +217,8 @@ py_getrandom(void *buffer, Py_ssize_t size, int blocking, int raise)
} }
return 1; return 1;
} }
#endif #endif /* defined(HAVE_GETRANDOM) || defined(HAVE_GETRANDOM_SYSCALL) */
static struct { static struct {
int fd; int fd;
@ -225,7 +226,6 @@ static struct {
ino_t st_ino; ino_t st_ino;
} urandom_cache = { -1 }; } urandom_cache = { -1 };
/* Read 'size' random bytes from py_getrandom(). Fall back on reading from /* Read 'size' random bytes from py_getrandom(). Fall back on reading from
/dev/urandom if getrandom() is not available. /dev/urandom if getrandom() is not available.
@ -236,22 +236,22 @@ dev_urandom(char *buffer, Py_ssize_t size, int blocking, int raise)
{ {
int fd; int fd;
Py_ssize_t n; Py_ssize_t n;
#ifdef PY_GETRANDOM #if defined(PY_GETRANDOM) || defined(PY_GETENTROPY)
int res; int res;
#endif
assert(size > 0); #ifdef PY_GETENTROPY
res = py_getentropy(buffer, size, raise);
#ifdef PY_GETRANDOM #else
res = py_getrandom(buffer, size, blocking, raise); res = py_getrandom(buffer, size, blocking, raise);
#endif
if (res < 0) { if (res < 0) {
return -1; return -1;
} }
if (res == 1) { if (res == 1) {
return 0; return 0;
} }
/* getrandom() failed with ENOSYS or EPERM, /* getrandom() or getentropy() function is not available: failed with
fall back on reading /dev/urandom */ ENOSYS or EPERM. Fall back on reading from /dev/urandom. */
#endif #endif
@ -349,8 +349,8 @@ dev_urandom_close(void)
urandom_cache.fd = -1; urandom_cache.fd = -1;
} }
} }
#endif /* !MS_WINDOWS */
#endif
/* Fill buffer with pseudo-random bytes generated by a linear congruent /* Fill buffer with pseudo-random bytes generated by a linear congruent
generator (LCG): generator (LCG):
@ -395,8 +395,6 @@ pyurandom(void *buffer, Py_ssize_t size, int blocking, int raise)
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
return win32_urandom((unsigned char *)buffer, size, raise); return win32_urandom((unsigned char *)buffer, size, raise);
#elif defined(PY_GETENTROPY)
return py_getentropy(buffer, size, raise);
#else #else
return dev_urandom(buffer, size, blocking, raise); return dev_urandom(buffer, size, blocking, raise);
#endif #endif
@ -491,8 +489,6 @@ _PyRandom_Fini(void)
CryptReleaseContext(hCryptProv, 0); CryptReleaseContext(hCryptProv, 0);
hCryptProv = 0; hCryptProv = 0;
} }
#elif defined(PY_GETENTROPY)
/* nothing to clean */
#else #else
dev_urandom_close(); dev_urandom_close();
#endif #endif