[Security-sig] PEP 524: Make os.urandom() blocking on Linux (version 3)

Victor Stinner victor.stinner at gmail.com
Fri Jul 29 10:21:17 EDT 2016


2016-07-29 15:31 GMT+02:00 Barry Warsaw <barry at python.org>:
> I agree that os.getrandom() should be added on platforms that support it
> regardless of the outcome of the various PEPs, and that it should be a thin
> layer above the C function.

Yes, in my PEP 524, os.getrandom() is a thin wrapper to getrandom().

Well, "thin" wrapper... An interesting question is if the function
should be implemented using a loop or only do exactly one call to
getrandom()?

Examples:

- getrandom() is limited to 1024 bytes on Solaris
- getrandom() can return less bytes than requested on Linux if the
call is interrupted by a signal.

If os.getrandom() only do a single call, the function must be called
in a loop at the Python level:

    result = bytearray()
    while size:
        data = os.getrandom(size)
        result += data
        size -= len(data)
    return bytes(result)

Currently, _PyOS_URandom() implements the loop at the C level.

The implementation of os.getrandom() must respect the PEP 475 (retry
syscall on EINTR), so maybe we should implement the loop at the C
level.

Ok, but imagine that you use the "expensive" GRNG_RANDOM (/dev/random
rather than /dev/urandom). A first call returns 4000 bytes of "high
quality" random bytes, but user requested 4096 bytes and the second
call fails.

Is it ok to "drop" the 4000 collected bytes? Entropy is a limited resource...

The strict minimum is to implement os.getrandom() with a single call,
*but* retry the getrandom() call if it fails with EINTR and the Python
signal handler doesn't raise any exception. With this design, we don't
drop any collected byte. But os.getrandom() should be used with a loop
at the Python level.

Victor


More information about the Security-SIG mailing list