@@ -15,8 +15,6 @@ static int _Py_HashSecret_Initialized = 0;
1515#endif
1616
1717#ifdef MS_WINDOWS
18- /* This handle is never explicitly released. Instead, the operating
19- system will release it when the process terminates. */
2018static HCRYPTPROV hCryptProv = 0 ;
2119
2220static int
@@ -38,7 +36,7 @@ win32_urandom_init(int raise)
3836}
3937
4038/* Fill buffer with size pseudo-random bytes generated by the Windows CryptoGen
41- API. Return 0 on success, or -1 on error. */
39+ API. Return 0 on success, or raise an exception and return -1 on error. */
4240static int
4341win32_urandom (unsigned char * buffer , Py_ssize_t size , int raise )
4442{
@@ -68,10 +66,35 @@ win32_urandom(unsigned char *buffer, Py_ssize_t size, int raise)
6866 }
6967 return 0 ;
7068}
71- #endif /* MS_WINDOWS */
7269
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.
7373
74- #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
7598static struct {
7699 int fd ;
77100 dev_t st_dev ;
@@ -203,7 +226,7 @@ dev_urandom_close(void)
203226 }
204227}
205228
206- #endif /* MS_WINDOWS */
229+ #endif /* HAVE_GETENTROPY */
207230
208231/* Fill buffer with pseudo-random bytes generated by a linear congruent
209232 generator (LCG):
@@ -244,6 +267,8 @@ _PyOS_URandom(void *buffer, Py_ssize_t size)
244267
245268#ifdef MS_WINDOWS
246269 return win32_urandom ((unsigned char * )buffer , size , 1 );
270+ #elif HAVE_GETENTROPY
271+ return py_getentropy (buffer , size , 0 );
247272#else
248273 return dev_urandom_python ((char * )buffer , size );
249274#endif
@@ -289,6 +314,8 @@ _PyRandom_Init(void)
289314 else {
290315#ifdef MS_WINDOWS
291316 (void )win32_urandom (secret , secret_size , 0 );
317+ #elif HAVE_GETENTROPY
318+ (void )py_getentropy (secret , secret_size , 1 );
292319#else
293320 dev_urandom_noraise (secret , secret_size );
294321#endif
@@ -298,7 +325,14 @@ _PyRandom_Init(void)
298325void
299326_PyRandom_Fini (void )
300327{
301- #ifndef MS_WINDOWS
328+ #ifdef MS_WINDOWS
329+ if (hCryptProv ) {
330+ CryptReleaseContext (hCryptProv , 0 );
331+ hCryptProv = 0 ;
332+ }
333+ #elif HAVE_GETENTROPY
334+ /* nothing to clean */
335+ #else
302336 dev_urandom_close ();
303337#endif
304338}
0 commit comments