kern/118062: /dev/random can be sniffed by an unprivileged user
freebsd-pr0711 at mlists.homeunix.com
Wed Nov 14 17:10:01 PST 2007
>Synopsis: /dev/random can be sniffed by an unprivileged user
>Arrival-Date: Thu Nov 15 01:10:01 UTC 2007
>Originator: Robert Woolley
FreeBSD gumby.homeunix.com. 6.2-RELEASE-p8 FreeBSD 6.2-RELEASE-p8 #2: Mon Nov 12 20:52:59 GMT 2007 root at gumby.homeunix.com.:/usr/obj/data/FreeBSD-src/sys/MUSTARD i386
It's possible for an unprivileged user to make /dev/random replay part of its most recent output. (This applies to Yarrow, not the hardware version.)
The first read must be 32 bytes or more, and the second 31 bytes or fewer. The worst case is when 32 bytes (256 bits) are followed by 31 bytes. It also appears to be possible, in theory, for an attacker to manipulate the state of the Yarrow implementation to maximize the number of replayed bytes, reducing 256 bits of entropy to 8bits. (it's actually easier to follow in the source)
$ dd if=/dev/random bs=32 count=1 2> /dev/null | hexdump ; dd if=/dev/random bs=31 count=1 2> /dev/null | hexdump
0000000 0ba3 af33 40ee b94e 0142 26f7 6ba1 3eba
0000010 38f6 3314 de4d 58a2 8f2a c4c1 b400 47f7
0000000 6ba1 3eba 38f6 3314 de4d 58a2 8f2a c4c1
0000010 b400 47f7 f937 985c 7f77 a7ae 8640 007c
Note that the sequence "6ba1 3eba 38f6 3314 de4d 58a2 8f2a c4c1 b400 47f7" appears in both outputs.
This might have to be run a few times if something else is reading from /dev/random.
The problem occurs in sys/dev/random/yarrow.c:random_yarrow_read()
This function handles requests based on the number of bytes requested. If less than 32 bytes, the random data is read out of a static buffer (genval) - keeping track of the remaining bytes in a variable called "cur". When cur is zero, the Yarrow cipher refills genval.
When larger requests are made, the genval buffer is immediately overwritten by the Yarrow cipher and copied into the output buffer. The is repeated until the request is satisfied. The problem is that this block of code leaves "cur" unmodified. This may cause the next request to reuse part of genval that's already been written-out.
cur should be set to the number of unused bytes (or just zeroed).
Patch attached with submission follows:
--- yarrow.c.orig Wed Nov 14 22:46:01 2007
+++ yarrow.c Wed Nov 14 22:48:54 2007
@@ -297,6 +297,7 @@
random_state.outputblocks = 0;
+ cur = (int)sizeof(random_state.counter) - (int)tomove;
retval += (int)tomove;
More information about the freebsd-bugs