Re: [PATCH v24 01/12] Linux Random Number Generator

From: Stephan Mueller
Date: Sun Nov 24 2019 - 04:06:00 EST


Am Sonntag, 24. November 2019, 05:51:19 CET schrieb Sandy Harris:

Hi Sandy,

> Stephan Müller <smueller@xxxxxxxxxx> wrote:
> > In an effort to provide a flexible implementation for a random number
> > generator that also ...
>
> As usual, some of your proposals make considerable sense to me &
> others do not, at least on first reading. I may have more comments
> after reflecting some.
>
> Meanwhile, a couple of things jump out at me:
> > (a) When an interrupt occurs, the high-resolution time stamp is mixed
> >
> > into the LFSR. ...
> >
> > (b) HID event data like the key stroke or the mouse coordinates are
> >
> > mixed into the LFSR. ...
> >
> > (c) Device drivers may provide data that is mixed into the LFSR. ...
>
> Why into the LFSR instead of into the entropy pool?

The LFSR is the state transitioning function of the entropy pool. Thus, when
handing data to the LFSR, it is "mixed" into the entropy pool. Thus, the LRNG
should perform the action you would expect, i.e. mixing the data into the
entropy pool.

>
> > The LRNG allows the TRNG and secondary DRNG mechanism to be changed
> > at runtime.
>
> Why? This strikes me as pointless complication.

The reason for this is the construction definition of the German AIS 31.

The TRNG is considered to operate as an NTG.1 in the terms of AIS 31. The
secondary DRNG(s) act as a DRG.3 in terms of AIS 31.

AIS 31 requires that DRGs (including a DRG.3) must be seeded from either an
NTG.1 (i.e. the TRNG) or a PTG (a physical noise source which we do not have
in the kernel).

This implies that the TRNG (NTG.1) seeds the secondary DRNG (DRG.3) and thus
would be compliant to AIS 31.

Since this construction method does not violate other construction methods,
such as the recommendations in SP800-90C, the LRNG architecture can be claimed
to be compliant with multiple different construction methods and requirements
where the output of either the TRNG or the secondary DRNGs always provide
random data from a compliant RNG.

Note, this construction is only applied if the TRNG is selected and compiled.
If the TRNG is not present (i.e. not compiled based on the Linux kernel
compilation configuration), the secondary DRNGs seed directly from the entropy
pool. Using this flexibility, the LRNG is intended to be able to serve
different use cases and requirements.
>
> > * high performance of interrupt handling code: The LRNG impact on the
> > interrupt handling has been reduced to a minimum. On one example
> > system, the LRNG interrupt handling code executes within an average
> > of 65 cycles whereas the existing /dev/random on the same device
> > takes about 97 cycles when measuring the execution time of
> > add_interrupt_randomness().
>
> Assuming you do this without sacrificing the input mixing, this
> would be worth submitting as a separate patch. Saving cycles
> on every interrupt definitely looks worth doing.
>
> > * lockless LFSR to collect raw entropy
>
> This too.

For both comments, the issue is that patches should always provide code that
compiles. The issue is that this logic cannot be extracted into a separate
patch without sacrificing the requirement to make it compile.

Though, the code you refer to is extracted into its own C file which allows an
independent assessment: please see lrng_sw_noise.c whose purpose is to only
provide the high-performance interrupt handling code. The lockless LFSR is
provided with the lrng_pool.c with the function lrng_pool_lfsr_u32.

PS: For those two functions and the ChaCha20 DRNG I have another patch in the
pipeline that will add power-on self tests which are automatically executed
during boot. Considering that these three functions are essential to the
maintenance of entropy, adding the self test for those should provide
additional assurance to users that the code runs properly.

PPS: If you want to study the operations of both, the high-performance
interrupt collection and the lockless LFSR, there is user space test code that
provides the implementation as a user space application: please see the test
code in [1] and use the code in:

- lfsr_demonstration.c: Full operational LFSR to generate arbitrary amounts of
data from arbitrary seed data.

- lfsr_testvector_generation.c: LFSR code that I used to generate self-test
vectors for the pending patch

- time_storage.c: Test code for the high-performance interrupt handling code

In addition the essential ChaCha20 DRNG is available as a user space DRNG for
study at [2].


[1] https://www.chronox.de/lrng.html

[2] https://www.chronox.de/chacha20_drng.html


Thank you very much for your considerations.

Ciao
Stephan