cpython: 980e2c781810 (original) (raw)
--- a/Python/random.c +++ b/Python/random.c @@ -39,10 +39,9 @@ win32_urandom_init(int raise) return 0; error:
@@ -55,8 +54,9 @@ win32_urandom(unsigned char *buffer, Py_ if (hCryptProv == 0) {
if (win32_urandom_init(raise) == -1)[](#l1.20)
if (win32_urandom_init(raise) == -1) {[](#l1.21) return -1;[](#l1.22)
} while (size > 0) @@ -65,11 +65,9 @@ win32_urandom(unsigned char buffer, Py_ if (!CryptGenRandom(hCryptProv, (DWORD)chunk, buffer)) { / CryptGenRandom() failed */}[](#l1.23)
if (raise)[](#l1.31)
if (raise) {[](#l1.32) PyErr_SetFromWindowsErr(0);[](#l1.33)
else[](#l1.34)
Py_FatalError("Failed to initialized the randomized hash "[](#l1.35)
"secret using CryptoGen)");[](#l1.36)
}[](#l1.37) return -1;[](#l1.38) }[](#l1.39) buffer += chunk;[](#l1.40)
@@ -86,29 +84,28 @@ win32_urandom(unsigned char buffer, Py_ / Fill buffer with size pseudo-random bytes generated by getentropy(). Return 0 on success, or raise an exception and return -1 on error.
- If raise is zero, don't raise an exception on error. */ static int -py_getentropy(unsigned char *buffer, Py_ssize_t size, int fatal) +py_getentropy(char *buffer, Py_ssize_t size, int raise) { while (size > 0) { Py_ssize_t len = Py_MIN(size, 256); int res;
if (!fatal) {[](#l1.56)
if (raise) {[](#l1.57) Py_BEGIN_ALLOW_THREADS[](#l1.58) res = getentropy(buffer, len);[](#l1.59) Py_END_ALLOW_THREADS[](#l1.60)
if (res < 0) {[](#l1.62)
PyErr_SetFromErrno(PyExc_OSError);[](#l1.63)
return -1;[](#l1.64)
}[](#l1.65) }[](#l1.66) else {[](#l1.67) res = getentropy(buffer, len);[](#l1.68)
if (res < 0)[](#l1.69)
Py_FatalError("getentropy() failed");[](#l1.70)
}[](#l1.71)
if (res < 0) {[](#l1.73)
if (raise) {[](#l1.74)
PyErr_SetFromErrno(PyExc_OSError);[](#l1.75)
}[](#l1.76)
return -1;[](#l1.77) }[](#l1.78)
buffer += len; @@ -195,18 +192,15 @@ py_getrandom(void *buffer, Py_ssize_t si if (errno == EINTR) { if (PyErr_CheckSignals()) {
if (!raise)[](#l1.85)
Py_FatalError("getrandom() interrupted by a signal");[](#l1.86) return -1;[](#l1.87) }[](#l1.88) /* retry getrandom() */[](#l1.89) continue;[](#l1.90) }[](#l1.91)
if (raise)[](#l1.93)
if (raise) {[](#l1.94) PyErr_SetFromErrno(PyExc_OSError);[](#l1.95)
else[](#l1.96)
Py_FatalError("getrandom() failed");[](#l1.97)
}[](#l1.98) return -1;[](#l1.99) }[](#l1.100)
@@ -225,9 +219,9 @@ static struct { /* Read size bytes from /dev/urandom into buffer.
- Call Py_FatalError() on error. */ -static void -dev_urandom_noraise(unsigned char *buffer, Py_ssize_t size)
- Return 0 success, or return -1 on error. */ +static int +dev_urandom_noraise(char *buffer, Py_ssize_t size) { int fd; Py_ssize_t n; @@ -235,31 +229,35 @@ dev_urandom_noraise(unsigned char *buffe assert (0 < size);
- if (py_getrandom(buffer, size, 0) == 1) {
return 0;[](#l1.122)
- } /* getrandom() is not supported by the running kernel, fall back
#endif fd = _Py_open_noraise("/dev/urandom", O_RDONLY);
while (0 < size) { do { n = read(fd, buffer, (size_t)size); } while (n < 0 && errno == EINTR);
if (n <= 0)[](#l1.140)
{[](#l1.141)
if (n <= 0) {[](#l1.143) /* stop on error or if read(size) returned 0 */[](#l1.144)
Py_FatalError("Failed to read bytes from /dev/urandom");[](#l1.145)
break;[](#l1.146)
return -1;[](#l1.147) }[](#l1.148)
+ buffer += n; size -= n; } close(fd); +
} /* Read size bytes from /dev/urandom into buffer. @@ -379,6 +377,40 @@ lcg_urandom(unsigned int x0, unsigned ch } } +/* If raise is zero:
- if (size < 0) {
if (raise) {[](#l1.172)
PyErr_Format(PyExc_ValueError,[](#l1.173)
"negative argument not allowed");[](#l1.174)
}[](#l1.175)
return -1;[](#l1.176)
- }
- if (raise) {
return dev_urandom_python(buffer, size);[](#l1.189)
- }
- else {
return dev_urandom_noraise(buffer, size);[](#l1.192)
- }
+#endif +} + /* Fill buffer with size pseudo-random bytes from the operating system random number generator (RNG). It is suitable for most cryptographic purposes except long living private keys for asymmetric encryption. @@ -387,21 +419,7 @@ lcg_urandom(unsigned int x0, unsigned ch int _PyOS_URandom(void *buffer, Py_ssize_t size) {
- if (size < 0) {
PyErr_Format(PyExc_ValueError,[](#l1.205)
"negative argument not allowed");[](#l1.206)
return -1;[](#l1.207)
- }
- if (size == 0)
return 0;[](#l1.210)
} void @@ -442,13 +460,14 @@ void } } else { -#ifdef MS_WINDOWS
(void)win32_urandom(secret, secret_size, 0);[](#l1.228)
(void)py_getentropy(secret, secret_size, 1);[](#l1.230)
dev_urandom_noraise(secret, secret_size);[](#l1.232)
int res;[](#l1.234)
/* _PyRandom_Init() is called very early in the Python initialization[](#l1.236)
* and so exceptions cannot be used. */[](#l1.237)
res = pyurandom(secret, secret_size, 0);[](#l1.238)
if (res < 0) {[](#l1.239)
Py_FatalError("failed to get random numbers to initialize Python");[](#l1.240)
} }}[](#l1.241)