lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20130922201436.GA4584@logfs.org>
Date:	Sun, 22 Sep 2013 16:14:36 -0400
From:	Jörn Engel <joern@...fs.org>
To:	Theodore Ts'o <tytso@....edu>
Cc:	John Stultz <john.stultz@...aro.org>,
	Stephan Mueller <smueller@...onox.de>,
	LKML <linux-kernel@...r.kernel.org>, dave.taht@...ferbloat.net,
	Frederic Weisbecker <fweisbec@...il.com>,
	Thomas Gleixner <tglx@...utronix.de>
Subject: Re: [PATCH,RFC] random: make fast_mix() honor its name

On Sat, 21 September 2013 17:25:10 -0400, Theodore Ts'o wrote:
> On Mon, Sep 16, 2013 at 11:40:27AM -0400, Jörn Engel wrote:
> > 
> > Here is a patch to make add_interrupt_randomness() significantly
> > cheaper without significantly impacting the quality.  The second part
> > is my personal opinion and others might disagree.
> > 
> > So far this has only seen userspace performance testing, so don't
> > merge it in a hurry.
> 
> Performance testing, but your new fast_mix pool has some serious
> problems in terms of how well it works.
> 
> First of all, I think this is a typo:
> 
> > +	for (i = 0; i < 3; i++) {
> 
> This means that pool[3] is always 0, and the input[3] is never mixed
> in.  Hence, the pool is now only 96 bits instead of 128 bits, and the
> last 4 bytes of the input pool are not getting mixed in.

Yes, indeed.

> Secondly, if you change this so that we actually use the whole pool,
> and you mix in a constant set of inputs like this:
> 
> 	for (i = 0; i < 100; i++) {
> 		input[0] = i;
> 		input[1] = i;
> 		input[2] = i;
> 		input[3] = i;
> 		fast_mix(&pool, input);
> 		print_pool(&pool);
> 	}
> 
> you see something like this:
> 
> pool:
>         0x00000000
>         0x00000000
>         0x00000000
>         0x00000000
> pool:
>         0x00000001
>         0x00000001
>         0x00000001
>         0x00000001
> pool:
>         0x00000082
>         0x00000082
>         0x00000082
>         0x00000082
> pool:
>         0x00004103
>         0x00004103
>         0x00004103
>         0x00004103
> pool:
>         0x00208184
>         0x00208184
>         0x00208184
>         0x00208184
> pool:
>         0x1040c205
>         0x1040c205
>         0x1040c205
>         0x1040c205
> 
> Granted, it's unlikely that we will be mixing numbers like this, but
> it's a great demonstration of why I added the input_rotate aspect to
> my mixing functions.

Honestly, this is a case of garbage in, garbage out.  If your
"randomness" is the same number repeated four times, the repetitions
don't add anything.  A more complicated mixing function doesn't buy
you much.  In the extreme case, you have the AES-encrypted counter
example.  No entropy on the input side, something that looks random on
the output side, and - because there is no secret key in the
complicated mixing function - anyone willing to sit down and do the
math can predict the output.

The failure case I was personally concerned about was a commutative
mixing function.  Interrupt numbers, for examples, are perfectly
predictable.  The randomness comes from the order or interrupts.  So
mix(a, b) != mix(b, a) is a hard requirement, if you excuse my silly
notation.

One variant that still fails your test above, but ensures every input
bit will eventually influence every output bit (certainly after 64
rounds) would be this:

static void fast_mix(struct fast_pool *f, __u32 input[4])
{
        int i;
        __u32 acc, p, carry = f->pool[3] >> 25;

        for (i = 0; i < 4; i++) {
                p = carry * input[i];
                acc = (f->pool[i] << 7) ^ input[i] ^ carry ^ p;
                carry = f->pool[i] >> 25;
                f->pool[i] = acc;
        }
}

Clearly this is a better mixing function, but I still think we don't
need that much quality.  If there is any randomness at all in the
interrupts, we will quickly make every bit in the pool unpredictable.
And if the interrupts are completely predictable in every bit and in
their order, well, we have lost either way.

Jörn

--
I say what I believe in.  And give reasons.
-- Pervez Hoodbhoy
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ