An example mdev.conf
Rob Landley
rob at landley.net
Sat Nov 7 21:40:46 UTC 2009
On Saturday 07 November 2009 10:46:35 Denys Vlasenko wrote:
> On Saturday 07 November 2009 05:56, Rob Landley wrote:
> > > random root:root 666
> > > urandom root:root 444
> > > hwrandom root:root 660
> > >
> > > random and urandom modes seem out of sync.
> >
> > He took the write bit off of urandom, but you can also write to urandom
> > to feed entropy back into the system
>
> But why in that file random is writable, and urandom is not?
Probably because he didn't _know_ you can feed entropy back into the entropy
pool through /dev/urandom the same way you can through /dev/random?
<rant>
You can't generate true random numbers in software (proof: run the same OS
snapshot twice under an emulator, it'll produce the same output), so if you
want unpredictable numbers for encryption keys and password salt and so on,
you need to get your randomness from unpredictable aspects of the hardware.
Cryptographers call this truly random data "entropy". Think television static
from the old analog TV sets of yore.
So the kernel collects all the random information it can from the hardware and
puts it in a buffer called an "entropy pool", which holds a few thousand bits
(I forget the exact size). Interrupt timings are a big source, _what_
interrupts come in may be predictable but exactly _when_ they come in measured
with a high resolution timer... not so much. (Keyboard key presses and mouse
movements keep the entropy buffer pretty constantly full on desktop systems.
Humans are great sources of randomness from a computer's perspective when you
look at the low bits of their I/O timing information.)
As entropy comes in the kernel mixes it into the pool using a hash function
(some variant of sha1sum I think) so no matter how small every new chunk of
random data is, mixing it in perturbs the whole buffer (just to give
cryptographers headaches). Then when they read data out of the buffer they
give it _another_ stir with the hash function so that even if no new entropy
is mixed in you get a big long stream of pseudo-random data, produced by the
hash function from the "seed" of the entropy pool.
But even though the whole entropy buffer looks like random noise, in theory if
you read enough data out of it without mixing in more entropy, a good
cryptogropher sniffs all that data and who knows your hash function could use
what they've already read to start predicting what comes next. (Of course
this assumes they've managed to crack root and freeze all other processes on
the system so none of them read any data out of the pool (thus giving the
cryptographer incomplete information to work with) and disabled every piece of
hardware that might produce fresh entropy (pretty much meaning interrupts
disabled), and don't have to worry about SMP or hyper-threading or preempt...
Did I mention cryptographers are professionally paranoid? See
http://www.networkworld.com/community/node/21935 for example.)
Anyway, the way they deal with this (largely theoretical) problem is by
tracking how many reliably random bits of entropy have been mixed into the
pool, and once they've read that many bits back out and you block until more
entropy gets mixed into the pool. (That way, you can guarantee that what they
_do_ read is unpredictable, but you can't guarantee their process will ever
complete.)
Note that some sources of entropy are considered suspect (such as disk
timings, which _might_ be locally measurable, or network packet interrupt
timings which somebody with wireshark and a really good clock might be able to
sniff going across the wire, maybe). Sometimes what they do is they mix a
large number of bits they harvested into the pool, but only account for a
smaller number of bits. "we collected 5 bits of data but only think there's
about 2 bits of real randomness in it". Because of the hash function, mixing
in extra predictable data still shouldn't yield a predictable result (or else
you're using a worthless hash function).
So that's what /dev/random does, block when the entropy accounting says we've
read out as many bits of randomness as we can _guarantee_ are unpredictable,
and waits for more entropy to come in. And what /dev/urandom does is let the
read continue to give you pseudo-random data the hash function's grinding out,
with arbitrary new entropy asynchronously dumped into the pool by interrupts,
even while you're reading.
When the system is freshly booted, the entropy pool is empty. The kernel
initializes the entropy pool with all the "unique to this system" information
it can find: mac addresses, cpuid, current clock time, and so on. But it sets
the entropy accounting to zero, because in theory all that data's somewhat
predictable. So /dev/urandom should give different information for each system
(and if you have a battery backed up clock, different information on each
boot), but it won't necessarily keep the NSA or the russian mafia from
decrypting your https transactions. (Generating a new pgp key right after the
system boots via an automatic script might not be your best move, but although
that's that's more or less what sshd does right after the OS install
generating your host keys. Current systems do that _after_ installing all the
OS packages, to let the disk I/O interrupt timings accumulate in the entropy
pool, if nothing else. And it's after the system prompts you for language and
time zone and stuff, so the user provided some entropy too if it's not an
automated install.)
To work around this problem, the kernel developers made /dev/random writable.
Any data you write to it gets mixed into the pool with the hash function,
although I dunno if this increases the entropy accounting (there were flamewars
over that, I forget the result).
This means that when you reboot the system, the shutdown scripts can read 512
bytes of random info from /dev/urandom (that's probably the whole pool, and
guaranteed not to block) and save it to a /tmp file, and then on the next boot
the init scripts write the contents of that file to /dev/random to perturb the
heck out of the entropy pool and hopefully make it as unpredictable as it was
last boot. (Of course they want to securely delete this /tmp file right after
using it so your NSA/mafia spook can't get ahold of it and use that to
reconstruct the entropy pool state.)
Embedded systems have a particularly hard time collecting entropy. They have
few devices generating interrupts. There's no keybaord and mouse, their hard
drive may not do anything after boot (and flash != hard drive anyway, the
timings of solid state hardware are a lot more predictable than moving parts),
and if you're not counting network packet timings as "unpredictable" you may
literally have NO sources of entropy in the system. Meaning /dev/random
blocks on embedded devices all the time and MAY NEVER UNBLOCK.
This is why lots of modern chipsets have hardware random number generators
built into 'em, so the entropy pool can be kept constantly full by an insane
little circut that does nothing but sit there and gibber electrically. It's
JOB is to generate static.
Failing that, a sound card with analog audio input counts as a hardware random
number generator (if you just listen to the low bits) even when no
microphone's plugged into it, so that's another thing the kernel can read from
to constantly keep the entropy pool full. (Most sound drivers these days are
aware of that and hook it up to the entropy pool, I think. And THAT is why so
many high bandwidth e-commerce servers have a sound card installed, because
serving 3-4 https transactions per second will keep the .)
In any case, lots of people use /dev/urandom for everything, becuase blocking
is a bad failure mode, and the real-world predictability of the urandom output
is pretty darn low on a system that's receiving _any_ entropy. Although the
problem there is you won't catch the ones that _aren't_ receiving any entropy
(servers and embedded devices), and if you give those a sound card or a
chipset with a HW random number generator then /dev/random should never block
either.
Oh, and emulators reopen this can of worms. A system under qemu is just as
bad off as an embedded system from a random number generator perspective, and
all the "virtual server" people who know what they're doing hook up a virtual
hardware random number generator that reads from the host's /dev/urandom to
pass through entropy to the emuluted system (which _can't_ harvest any
meaningfully from the hardwrae, because its hardware is software and software
is by its nature deterministic and predictable.)
Example from User Mode Linux:
http://lkml.indiana.edu/hypermail/linux/kernel/0503.1/0823.html
Alas, neither QEMU nor KVM seem to have this yet. I guess they use the
virtual sound cards?
</rant>
Rob
--
Latency is more important than throughput. It's that simple. - Linus Torvalds
More information about the busybox
mailing list