Collecting entropy from device_attach() times.
Bruce Evans
brde at optusnet.com.au
Thu Sep 27 23:43:23 UTC 2012
On Fri, 28 Sep 2012, [utf-8] Dag-Erling Smørgrav wrote:
> Bruce Evans <brde at optusnet.com.au> writes:
>> "Dag-Erling Smørgrav" <des at des.no> writes:
>>> RW <rwmaillists at googlemail.com> writes:
>>>> binuptime(&bt);
>>>> return (bt.frac ^ bt.sec);
>>> Why the heck does it xor the integer and fractional parts together?
>> Because most of the entropy is in the fractional part,
>
> This is not about entropy, it's about implementing get_cyclecount() on a
> platform that doesn't have a TSC. It's supposed to be monotonic, and
> this implementation clearly isn't. Even when bt.sec is small enough
Its monotonicity and documentation of same is a bug.
> that it doesn't affect significant digits of bt.frac (which should be
> most of the time, unless the resolution of the underlying timecounter
> exceeds ~2^32 Hz), get_cyclecount() will go backward every time a new
> second ticks over.
Its implementation demonstrates that it was never actually monotonic.
Even rdtsc() isn't necessarily monotonic.
Its comment in at least the i386 version still says that it "Return[s]
contents of an in-cpu fast counter as a sort of "bogo-time" for random-
harvesting purposes". This has rotted in various ways:
- on i386 without tsc_present, it never used an in-cpu fast counter
(since there is none)
- on i386, without tsc_present, it now uses the generic cpu_ticks()
and gets whatever that gives, which happens to be a more monotonic
less bogus time that before, and which doesn't have the xor hack.
- on i386, with tsc_present, it now uses the generic cpu_ticks()
and gets whatever that gives, which happens to be the same in-cpu
fast counter as before.
It shouldn't be commenting about what cpu_ticks() [doesn't] do.
- its man page says that it uses a "register available in most modern
CPUs to return a value that is monotonically increasing inside each
CPU", and explicitly documents that each CPU gives a separate monotonic
sequence. A strict reading of this says that it doesn't exist on
non-modern CPUs or on some modern CPUS. Bugs in this include:
- over-specification of implementation details. Lots of bugs in the
details:
- at least in i386, the value isn't necessarily increasing even with
in each CPU, since rdtsc() isn't serialized and maybe something
resets the register. The implementation just uses rdtsc() without
worrying about these points.
- on more modern CPUs, the values are synced, so the sequences aren't
separate.
- guaranteeing monotonicity.
- it is now abused for non-random-harvesting purposes, and some of these
require it to be monotonic. These places mostly just want a timestamp
for debugging and should be using microtime(). See one of my old mails
for full details of this and more details of the bogusness of
get_cyclecount().
I should have objected more strongly when it was implemented. Just using
binuptime() was adequate iff the timecounter hardware is the same as
the cycle counter (TSC on x86). A TSC usable for timecounter hardware is
normal now. I don't like cpu_tick() either, but it solves the efficiency
problem with the timecounter hardware not being the cycle counter. It
solves them for use mainly in thread runtime accounting, but is usable
for get_cyclecount() too, and is in fact used for get_cyclecount() on i386
(get_cyclecount() just wraps it and no one except bde cares about the
inefficiency of this). cpu_tick() is undocumented, so there are no bugs
in its man page to fix.
Bruce
More information about the freebsd-security
mailing list