[Security-sig] RFC: PEP: Make os.urandom() blocking on Linux
Nick Coghlan
ncoghlan at gmail.com
Thu Jun 23 20:56:21 EDT 2016
On 23 June 2016 at 11:38, Nick Coghlan <ncoghlan at gmail.com> wrote:
> Although now I'm wondering whether it might be worth proposing a
> "secrets.wait_for_system_rng()" API as part of PEP 522, with the
> following implementation:
>
> def wait_for_system_rng():
> # Avoid the below busy loop if possible
> try:
> block_on_system_rng = open("/dev/random", "rb")
> except FileNotFoundError:
> pass
> else:
> with block_on_system_rng:
> block_on_system_rng.read(1)
> # Busy loop until the system RNG is ready
> while True:
> try:
> os.urandom(1)
> break
> except BlockingIOError:
> pass
I realised even this more complex variant still has a subtle bug: due
to the way /dev/random works, it can block inappropriately if Python
is started after the system RNG has already been seeded. That means a
completely correct implementation (assuming the rest of PEP 522 was in
place) would look more like this:
def wait_for_system_rng():
# If the system RNG is already seeded, don't wait at all
try:
os.urandom(1)
return
except BlockingIOError:
pass
# Avoid the below busy loop if possible
try:
block_on_system_rng = open("/dev/random", "rb")
except FileNotFoundError:
pass
else:
with block_on_system_rng:
block_on_system_rng.read(1)
# Busy loop until the system RNG is ready
while True:
try:
os.urandom(1)
break
except BlockingIOError:
# Only check once per millisecond
time.sleep(0.001)
So I'll update PEP 522 to include this as part of the proposal - it's
trickier to get right than I thought, and it provides an additional
hook to help explain that the system RNG is something that once
initialized, stays initialized, so waiting for it is best handled as
an application level and system configuration concern rather than on
each call to os.urandom().
It also enables a pretty neat ExecStartPre [1] trick in systemd unit files:
ExecStartPre=/usr/bin/python3 -c "import secrets;
secrets.wait_for_system_rng()"
to make an arbitrary service wait until the system RNG is ready before it runs.
Cheers,
Nick.
[1] https://www.freedesktop.org/software/systemd/man/systemd.service.html#ExecStartPre=
--
Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia
More information about the Security-SIG
mailing list