jirka-h / haveged

Entropy daemon ![Continuous Integration](https://github.com/jirka-h/haveged/workflows/Continuous%20Integration/badge.svg)
GNU General Public License v3.0
273 stars 34 forks source link

haveged test suite passes even if only `1`s are produced? #81

Closed adrelanos closed 2 months ago

adrelanos commented 3 months ago

Quote https://jakob.engbloms.se/archives/1374

So I tried to remove all variations from the HAVEGE program. I replaced the “HARDTICKS” macro in HAVEGE with the constant 0 (zero) rather than reading the time stamp counter of the processor. This immediately failed the randomness test.

However, when I used the constant 1 (one) instead, the ent test passed. And even nist almost passed with only a single missed test out of the 426 tests executed.

ArrayBolt3 commented 2 months ago

I don't think this means what it looks like it means. As the author of haveged pointed out in the article, it is expected that haveged will return high-quality pseudorandom data even if it is unable to extract any non-deterministic data from the system it runs on. Assuming the PRNG used inside of it is any good, it should produce pseudorandom data sufficient to pass most tests even when no entropy is being input. It's not outputting all 1s, it's receiving only deterministic data as input, one part that input always being 1.

ArrayBolt3 commented 2 months ago

To further verify, I modified one of the files such that it should make haveged only ever output 1:

@@ -253,7 +253,8 @@ int havege_rng(            /* RETURN: number words read     */
    H_UINT i;

    for(i=0;i<sz;i++)
-      buffer[i] = havege_ndread((H_COLLECT *)h->collector);
+      buffer[i] = 1; // YIKES! Don't ever let this into production, this is for testing purposes only.
+      //buffer[i] = havege_ndread((H_COLLECT *)h->collector);
    h->error = ((H_COLLECT *)h->collector)->havege_err;
 #endif
    return h->error==(H_UINT)H_NOERR? (int) sz : -1;

As expected, this flunked all of the RNG tests, including ent and nist tests. Results from the ent tests:

┌─╴aaron@kf-ir16:/srv/data/vmshare/kicksecure/git/haveged
└─╴$ make check
Making check in src
make[1]: Entering directory '/srv/data/vmshare/kicksecure/git/haveged/src'
make[1]: Nothing to be done for 'check'.
make[1]: Leaving directory '/srv/data/vmshare/kicksecure/git/haveged/src'
Making check in man
make[1]: Entering directory '/srv/data/vmshare/kicksecure/git/haveged/man'
make[1]: Nothing to be done for 'check'.
make[1]: Leaving directory '/srv/data/vmshare/kicksecure/git/haveged/man'
Making check in ent
make[1]: Entering directory '/srv/data/vmshare/kicksecure/git/haveged/ent'
make  entest
make[2]: Entering directory '/srv/data/vmshare/kicksecure/git/haveged/ent'
gcc -DHAVE_CONFIG_H -I. -I..    -Wall -g -O2 -c -o entest.o entest.c
gcc -DHAVE_CONFIG_H -I. -I..    -Wall -g -O2 -c -o iso8859.o iso8859.c
gcc -DHAVE_CONFIG_H -I. -I..    -Wall -g -O2 -c -o randtest.o randtest.c
gcc -DHAVE_CONFIG_H -I. -I..    -Wall -g -O2 -c -o chisq.o chisq.c
/bin/bash ../libtool  --tag=CC   --mode=link gcc -Wall -g -O2   -o entest entest.o iso8859.o randtest.o chisq.o -lm 
libtool: link: gcc -Wall -g -O2 -o entest entest.o iso8859.o randtest.o chisq.o  -lm
make[2]: Leaving directory '/srv/data/vmshare/kicksecure/git/haveged/ent'
make  check-local
make[2]: Entering directory '/srv/data/vmshare/kicksecure/git/haveged/ent'
./entest -t ./entitle.gif
Self-test good!
./test.sh
Writing 16 M byte output to stdout
Writing 16 M byte output to stdout
Writing 16 M byte output to stdout
Writing 16 M byte output to stdout
Writing 16 M byte output to stdout
Writing 16 M byte output to stdout
Writing 16 M byte output to stdout
Writing 16 M byte output to stdout
Writing 16 M byte output to stdout
Writing 16 M byte output to stdout
Total 10 in 10
./01_entest.log:Check Fail: entropy:0.811278<7.500000 chisqr:0.000000% not in 1.000000-99.000000 mean:0.250000<127.000000 pi:4.000000 27.323954>0.500000 
./02_entest.log:Check Fail: entropy:0.811278<7.500000 chisqr:0.000000% not in 1.000000-99.000000 mean:0.250000<127.000000 pi:4.000000 27.323954>0.500000 
./03_entest.log:Check Fail: entropy:0.811278<7.500000 chisqr:0.000000% not in 1.000000-99.000000 mean:0.250000<127.000000 pi:4.000000 27.323954>0.500000 
./04_entest.log:Check Fail: entropy:0.811278<7.500000 chisqr:0.000000% not in 1.000000-99.000000 mean:0.250000<127.000000 pi:4.000000 27.323954>0.500000 
./05_entest.log:Check Fail: entropy:0.811278<7.500000 chisqr:0.000000% not in 1.000000-99.000000 mean:0.250000<127.000000 pi:4.000000 27.323954>0.500000 
./06_entest.log:Check Fail: entropy:0.811278<7.500000 chisqr:0.000000% not in 1.000000-99.000000 mean:0.250000<127.000000 pi:4.000000 27.323954>0.500000 
./07_entest.log:Check Fail: entropy:0.811278<7.500000 chisqr:0.000000% not in 1.000000-99.000000 mean:0.250000<127.000000 pi:4.000000 27.323954>0.500000 
./08_entest.log:Check Fail: entropy:0.811278<7.500000 chisqr:0.000000% not in 1.000000-99.000000 mean:0.250000<127.000000 pi:4.000000 27.323954>0.500000 
./09_entest.log:Check Fail: entropy:0.811278<7.500000 chisqr:0.000000% not in 1.000000-99.000000 mean:0.250000<127.000000 pi:4.000000 27.323954>0.500000 
./10_entest.log:Check Fail: entropy:0.811278<7.500000 chisqr:0.000000% not in 1.000000-99.000000 mean:0.250000<127.000000 pi:4.000000 27.323954>0.500000 
Marking the whole test as failed
make[2]: *** [Makefile:574: check-local] Error 255
make[2]: Leaving directory '/srv/data/vmshare/kicksecure/git/haveged/ent'
make[1]: *** [Makefile:446: check-am] Error 2
make[1]: Leaving directory '/srv/data/vmshare/kicksecure/git/haveged/ent'
make: *** [Makefile:479: check-recursive] Error 1
adrelanos commented 2 months ago

Great, so this issue does not exist. Thank you!