While I was originally planning to write a tiny SNMP daemon for my
geiger counter so as to graph trends, I decided instead to write a kernel module exposing the counters. This way, my system can use the interrupt events as a source of true randomness (radioactive decay is, by definition, truly random).
First, a quick introduction to the random number generation bits in Linux:
drivers/char/random.c. This module in essence keeps track of two things: a seed value, and a pool of entropic data to mix in. At boot, the seed is set to the previous shutdown value (if available), then mixed with device-constant sources of entropy such as MAC addresses, serial numbers, and so forth. While running, drivers such as keyboards, mice, and disk controllers contribute to seed entropy by calling one of the add_*_randomness() functions defined and exported from random.c. These functions keep track of time deltas between calls, mixing the seed value with new values from the entropy pool between reads.
The random module presents two char devices for userspace to get data: /dev/random and /dev/urandom. On each read(), an SHA1 hash is taken of the current seed value and returned to the user. This result is then mixed with the seed value itself as well as some data from the entropy pool. The difference between them is this: if the entropy pool becomes depleted after successive reads, /dev/random will block until more entropy data is available to mix in and hash, thus ensuring the output is non-deterministic. However, /dev/urandom will continue returning pseudorandom data even without entropy, simply mixing the seed with the resultant SHA1 hash each time around. Determining the seed value and predicting the output would require an inverse of SHA1 (no small feat), but it is nonetheless mathematically possible to do so given enough resources.
As you can see, sources of good entropy are extremely important for reasonably random numbers. While human input sources like the keyboard and mouse are still valid, disk access time data is no longer usable with SSDs due to their highly characterizable behavior. Companies like Intel have
implemented hardware randomness and key generation functionality, the closed-source nature of the beast has been cause for skepticism particularly in the post-NSA revelation climate - for instance, OpenSSL still doesn't use the Intel key generation instructions for AES despite significant speed benefits. The point to all of this is that good random seed data is hard to get, and radioactive decay is a great source.
Back to the task subject at hand: Radseed listens for hardware interrupts on the ACK line of the parallel port. When such an event is detected, the events counter is incremented and time of last event (in jiffies) recorded.
jackc@kdev0 ~ $ cat /sys/kernel/radseed/events
41
jackc@kdev0 ~ $ cat /sys/kernel/radseed/last
16316569
If you want to test graphs or whatnot without a geiger counter connected, you can trigger events manually too:
jackc@kdev0 ~ $ cat /sys/kernel/radseed/trigger
1
jackc@kdev0 ~ $ cat /sys/kernel/radseed/events
42
jackc@kdev0 ~ $ cat /sys/kernel/radseed/last
16378144
Since very few things even have parallel ports anymore (plus I have a bunch of geiger-muller tubes sitting here), I'm working on a board design for a small USB geiger counter that doesn't need external power and can be plugged into anything for easy external entropy.
Code is on GitHub:
jackcarrozzo/radseed.