Package: rng-tools
Version: 2-unofficial-mt.14-1
Severity: normal
Tags: patch

Hi,

So I recently wrote some code to do the FIPS 140 tests, and though test
suites are good and all that, for something like this I also wanted to
run it against an independent implementation as a cross correlation on
sanity, and found the code in rng-tools which looked like it would be a
good candidate for that ...

Except they disagreed on a small, but large enough to be disturbing,
number of blocks for the Runs and Poker tests.  At first glance we did
appear to be using the same thresholds, so clearly Something Was Wrong.

Happily (for me :), it turns out that my code was correct.
Also happily (for you, I hope ;), I've attached a patch that fixes two
bugs in the Runs test in rng-tools (which broke both tests).

You can pull it from here:
http://anonscm.debian.org/cgit/users/ron/rng-tools.git/commit/?id=27c260ae79e3b02f81062328497648b1e5f46613

And if reportbug --attach actually worked, the git-format-patch export
should be included in this mail.  There's a full description of the
bugs in the commit message of it.

This might be a good one to also push upstream, if they haven't found
and fixed it already.  I've only looked at the code in your fork so far.

  Cheers,
  Ron
>From 27c260ae79e3b02f81062328497648b1e5f46613 Mon Sep 17 00:00:00 2001
From: Ron <[email protected]>
Date: Sat, 24 Jan 2015 19:12:50 +1030
Subject: [PATCH] Fix the broken FIPS 140-2 runs test

There were two (related) bugs in the Runs test that this patch fixes.

The first is it was not handling the special case of ctx->rlength == -1
so if the first bit of a block was not equal to ctx->last_bit (which is
either carried over 'uselessly' from the previous block or set to 0 for
the very first bit of a testing session, but either way is 'random' at
the start of a new block), then it will try to record that event into
ctx->runs[-1 + (6 * ctx->current_bit)].  Which in the 'best' case, will
record it as a run of 0's when it should have been a run of one 1's,
and in the worst case will instead increment ctx->poker[15] (when the
fips_ctx_t struct isn't padded between those two fields).

In any reasonable length run it will hit both cases and break both the
Runs test and the Poker test results.

The second bug is that the same code was wrongly incrementing the count
for ctx->current_bit, when the run it observed is actually instead for
ctx->last_bit.  This wouldn't make a whole lot of difference to the end
result, except for the code outside of that loop which records the
final run of the block (correctly) for ctx->current_bit.  That means
the final run will record 0's or 1's into the opposite set of bins that
the main processing loop does, again (in the worst case) resulting in a
wrong count for some run length of both 0's and 1's, which some portion
of the time will cause a false (positive or negative) Runs test result.

Signed-off-by: Ron <[email protected]>
---
 fips.c | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/fips.c b/fips.c
index a4d5e32..f1c82ca 100644
--- a/fips.c
+++ b/fips.c
@@ -93,11 +93,10 @@ static void fips_test_store(fips_ctx_t *ctx, unsigned int rng_data)
 		if (ctx->current_bit != ctx->last_bit) {
 			/* If runlength is 1-6 count it in correct bucket. 0's go in
 			   runs[0-5] 1's go in runs[6-11] hence the 6*current_bit below */
-			if (ctx->rlength < 5) {
-				ctx->runs[ctx->rlength +
-				     (6 * ctx->current_bit)]++;
-			} else {
-				ctx->runs[5 + (6 * ctx->current_bit)]++;
+			if (ctx->rlength > 4) {
+				ctx->runs[5 + (6 * ctx->last_bit)]++;
+			} else if (ctx->rlength >= 0 ) {
+				ctx->runs[ctx->rlength + (6 * ctx->last_bit)]++;
 			}
 
 			/* Check if we just failed longrun test */
-- 
2.1.1

Reply via email to