@@ -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. */
4040static int
4141win32_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
7398static 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
0 commit comments