Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 4d6a3d6

Browse files
committed
Issue #22585: On OpenBSD 5.6 and newer, os.urandom() now calls getentropy(),
instead of reading /dev/urandom, to get pseudo-random bytes.
1 parent 3c6fe4d commit 4d6a3d6

6 files changed

Lines changed: 50 additions & 6 deletions

File tree

Lib/test/test_os.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import decimal
2828
import fractions
2929
import pickle
30+
import sysconfig
3031
try:
3132
import threading
3233
except ImportError:
@@ -1103,6 +1104,12 @@ def test_urandom_subprocess(self):
11031104
data2 = self.get_urandom_subprocess(16)
11041105
self.assertNotEqual(data1, data2)
11051106

1107+
1108+
HAVE_GETENTROPY = (sysconfig.get_config_var('HAVE_GETENTROPY') == 1)
1109+
1110+
@unittest.skipIf(HAVE_GETENTROPY,
1111+
"getentropy() does not use a file descriptor")
1112+
class URandomFDTests(unittest.TestCase):
11061113
@unittest.skipUnless(resource, "test requires the resource module")
11071114
def test_urandom_failure(self):
11081115
# Check urandom() failing when it is not able to open /dev/random.

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,9 @@ Core and Builtins
196196
Library
197197
-------
198198

199+
- Issue #22585: On OpenBSD 5.6 and newer, os.urandom() now calls getentropy(),
200+
instead of reading /dev/urandom, to get pseudo-random bytes.
201+
199202
- Issue #19104: pprint now produces evaluable output for wrapped strings.
200203

201204
- Issue #23071: Added missing names to codecs.__all__. Patch by Martin Panter.

Python/random.c

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ win32_urandom_init(int raise)
3636
}
3737

3838
/* Fill buffer with size pseudo-random bytes generated by the Windows CryptoGen
39-
API. Return 0 on success, or -1 on error. */
39+
API. Return 0 on success, or raise an exception and return -1 on error. */
4040
static int
4141
win32_urandom(unsigned char *buffer, Py_ssize_t size, int raise)
4242
{
@@ -66,10 +66,35 @@ win32_urandom(unsigned char *buffer, Py_ssize_t size, int raise)
6666
}
6767
return 0;
6868
}
69-
#endif /* MS_WINDOWS */
7069

70+
#elif HAVE_GETENTROPY
71+
/* Fill buffer with size pseudo-random bytes generated by getentropy().
72+
Return 0 on success, or raise an exception and return -1 on error.
7173
72-
#ifndef MS_WINDOWS
74+
If fatal is nonzero, call Py_FatalError() instead of raising an exception
75+
on error. */
76+
static int
77+
py_getentropy(unsigned char *buffer, Py_ssize_t size, int fatal)
78+
{
79+
while (size > 0) {
80+
Py_ssize_t len = Py_MIN(size, 256);
81+
int res = getentropy(buffer, len);
82+
if (res < 0) {
83+
if (fatal) {
84+
Py_FatalError("getentropy() failed");
85+
}
86+
else {
87+
PyErr_SetFromErrno(PyExc_OSError);
88+
return -1;
89+
}
90+
}
91+
buffer += len;
92+
size -= len;
93+
}
94+
return 0;
95+
}
96+
97+
#else
7398
static struct {
7499
int fd;
75100
dev_t st_dev;
@@ -201,7 +226,7 @@ dev_urandom_close(void)
201226
}
202227
}
203228

204-
#endif /* MS_WINDOWS */
229+
#endif /* HAVE_GETENTROPY */
205230

206231
/* Fill buffer with pseudo-random bytes generated by a linear congruent
207232
generator (LCG):
@@ -242,6 +267,8 @@ _PyOS_URandom(void *buffer, Py_ssize_t size)
242267

243268
#ifdef MS_WINDOWS
244269
return win32_urandom((unsigned char *)buffer, size, 1);
270+
#elif HAVE_GETENTROPY
271+
return py_getentropy(buffer, size, 0);
245272
#else
246273
return dev_urandom_python((char*)buffer, size);
247274
#endif
@@ -287,6 +314,8 @@ _PyRandom_Init(void)
287314
else {
288315
#ifdef MS_WINDOWS
289316
(void)win32_urandom(secret, secret_size, 0);
317+
#elif HAVE_GETENTROPY
318+
(void)py_getentropy(secret, secret_size, 1);
290319
#else
291320
dev_urandom_noraise(secret, secret_size);
292321
#endif
@@ -301,6 +330,8 @@ _PyRandom_Fini(void)
301330
CryptReleaseContext(hCryptProv, 0);
302331
hCryptProv = 0;
303332
}
333+
#elif HAVE_GETENTROPY
334+
/* nothing to clean */
304335
#else
305336
dev_urandom_close();
306337
#endif

configure

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10697,7 +10697,7 @@ fi
1069710697
for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
1069810698
clock confstr ctermid dup3 execv faccessat fchmod fchmodat fchown fchownat \
1069910699
fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
10700-
futimens futimes gai_strerror \
10700+
futimens futimes gai_strerror getentropy \
1070110701
getgrouplist getgroups getlogin getloadavg getpeername getpgid getpid \
1070210702
getpriority getresuid getresgid getpwent getspnam getspent getsid getwd \
1070310703
if_nameindex \

configure.ac

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3004,7 +3004,7 @@ fi
30043004
AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
30053005
clock confstr ctermid dup3 execv faccessat fchmod fchmodat fchown fchownat \
30063006
fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
3007-
futimens futimes gai_strerror \
3007+
futimens futimes gai_strerror getentropy \
30083008
getgrouplist getgroups getlogin getloadavg getpeername getpgid getpid \
30093009
getpriority getresuid getresgid getpwent getspnam getspent getsid getwd \
30103010
if_nameindex \

pyconfig.h.in

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,9 @@
332332
/* Define this if you have flockfile(), getc_unlocked(), and funlockfile() */
333333
#undef HAVE_GETC_UNLOCKED
334334

335+
/* Define to 1 if you have the `getentropy' function. */
336+
#undef HAVE_GETENTROPY
337+
335338
/* Define to 1 if you have the `getgrouplist' function. */
336339
#undef HAVE_GETGROUPLIST
337340

0 commit comments

Comments
 (0)