linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v24 00/12] /dev/random - a new approach with full SP800-90B compliance
@ 2019-11-11 18:17 Stephan Müller
  2019-11-11 18:18 ` [PATCH v24 01/12] Linux Random Number Generator Stephan Müller
                   ` (14 more replies)
  0 siblings, 15 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-11 18:17 UTC (permalink / raw)
  To: Arnd Bergmann, Greg Kroah-Hartman
  Cc: linux-crypto, LKML, linux-api, Eric W. Biederman,
	Alexander E. Patrakov, Ahmed S. Darwish, Theodore Y. Ts'o,
	Willy Tarreau, Matthew Garrett, Vito Caputo, Andreas Dilger,
	Jan Kara, Ray Strode, William Jon McCann, zhangjs,
	Andy Lutomirski, Florian Weimer, Lennart Poettering,
	Nicolai Stange, Peter, Matthias, Marcelo Henrique Cerri,
	Roman Drahtmueller, Neil Horman

Hi,

The following patch set provides a different approach to /dev/random which is
called Linux Random Number Generator (LRNG) to collect entropy within the Linux
kernel. The main improvements compared to the existing /dev/random is to provide
sufficient entropy during boot time as well as in virtual environments and when
using SSDs. A secondary design goal is to limit the impact of the entropy
collection on massive parallel systems and also allow the use accelerated
cryptographic primitives. Also, all steps of the entropic data processing are
testable.

The LRNG patch set allows a user to select use of the existing /dev/random or
the LRNG during compile time. As the LRNG provides API and ABI compatible
interfaces to the existing /dev/random implementation, the user can freely chose
the RNG implementation without affecting kernel or user space operations.

This patch set provides early boot-time entropy which implies that no
additional flags to the getrandom(2) system call discussed recently on
the LKML is considered to be necessary.

The LRNG is fully compliant to SP800-90B requirements and is shipped with a
full SP800-90B assessment and all required test tools. The existing /dev/random
implementation on the other hand has architectural limitations which
does not easily allow to bring the implementation in compliance with
SP800-90B. The key statement that causes concern is SP800-90B section
3.1.6. This section denies crediting entropy to multiple similar noise
sources. This section explicitly references different noise sources resting
on the timing of events and their derivatives (i.e. it is a direct complaint
to the existing existing /dev/random implementation). Therefore, SP800-90B
now denies the very issue mentioned in [1] with the existing /dev/random
implementation for a long time: crediting entropy to interrupts as well as
crediting entropy to derivatives of interrupts (HID and disk events). This is
not permissible with SP800-90B.

SP800-90B specifies various requirements for the noise source(s) that seed any
DRNG including SP800-90A DRBGs. In about a year from now, SP800-90B will be
mandated for all noise sources that provide entropy to DRBGs as part of a FIPS
140-[2|3] validation or other evaluation types. That means, if we there are no
solutions to comply with the requirements of SP800-90B found till one year
from now, any random number generation and ciphers based on random numbers
on Linux will be considered and treated as not applicable and delivering
no entropy! As /dev/urandom, getrandom(2) and /dev/random are the most
common and prevalent noise sources for DRNGs, all these DRNGs are affected.
This applies across the board for all validations of cryptography executing on
Linux (kernel and user space modules).

For users that are not interested in SP800-90B, the entire code for the
compliance as well as test interfaces can be deselected at compile time.

The design and implementation is driven by a set of goals described in [1]
that the LRNG completely implements. Furthermore, [1] includes the full
assessment of the SP800-90B compliance as well as a comparison with RNG
design suggestions of SP800-90C, and AIS20/31.

The LRNG provides a complete separation of the noise source maintenance
and the collection of entropy into an entropy pool from the post-processing
using a pseudo-random number generator. Different DRNGs are supported,
including:

* The LRNG can be compile-time enabled to replace the existing /dev/random
  implementation. When not selecting the LRNG at compile time (default), the
  existing /dev/random implementation is built.

* Built-in ChaCha20 DRNG which has no dependency to other kernel
  frameworks.

* SP800-90A DRBG using the kernel crypto API including its accelerated
  raw cipher implementations. This implies that the output of /dev/random,
  getrandom(2), /dev/urandom or get_random_bytes is fully compliant to
  SP800-90A.

* Arbitrary DRNGs registered with the kernel crypto API

* Full compliance with SP800-90B which covers the startup and runtime health
  tests mandated by SP800-90B as well as providing the test tools and test
  interfaces to obtain raw noise data securely. The test tools are provided at
  [1].

Booting the patch with the kernel command line option
"dyndbg=file drivers/char/lrng* +p" generates logs indicating the operation
of the LRNG. Each log is pre-pended with "lrng".

The LRNG has a flexible design by allowing an easy replacement of the
deterministic random number generator component.

Compared to the existing /dev/random implementation, the compiled binary
is smaller when the LRNG is compiled with all options equal to the
existing /dev/random (i.e. only CONFIG_LRNG and
CONFIG_LRNG_TRNG_SUPPORT are set): random.o is 52.5 kBytes whereas
all LRNG object files are in 49 kBytes in size. The fully
SP800-90A/SP800-90B compliant binary code (CONFIG_LRNG,
CONFIG_LRNG_DRNG_SWITCH, CONFIG_LRNG_DRBG, CONFIG_LRNG_HEALTH_TESTS)
uses some 61 kBytes.

[1] http://www.chronox.de/lrng.html - If the patch is accepted, I would
be volunteering to convert the documentation into RST format and
contribute it to the Linux kernel documentation directory.

Changes (compared to the previous patch set for 5.2):

* breakup of the monolithic code base into several logically isolated
  files and move all files into drivers/char/lrng/ - this also reduces
  the number of ifdefs in the code significantly as the make system is
  used to select the enabled code

* Add Tested-by and Reviewed-by lines

* Significant speedup of code executing in interrupt handler: the LRNG
  is now almost 50% faster as the existing /dev/random. 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.

* SP800-90B compliance
	- use hash_df function defined in SP800-90A section 10.3.1 to read
	  entropy pool
	- add compile time configurable SP800-90B health tests and eliminate
	  any FIPS 140-2 code from the base code
	- consider entropy reduction of conditioning operation compliant
	  to SP800-90B
	- complete entropy assessment and entropy assessment tests available
	at [1]

* prune base LRNG code of any FIPS-related code - all FIPS-related code is
  in the SP800-90B compliance code that can be deactivated at compile time

* testing performed with all tests offered at [1] including all required
  SP800-90B tests, as well as KASAN, UBSAN, and lockdep while executing
  stress tests. Tests were performed on: x86, S390

* make DRNG switching support compile-time configurable

* selection of entropy pool size is now a configure option

* support deactivation of TRNG (i.e. blocking behavior of /dev/random)
  at compile time. If deactivated, /dev/random behaves like
  getrandom(2).

* conditionally compile NUMA support

* eliminate in_atomic() invocation: In-kernel consumers always use
  the ChaCha20 DRNG unless the new API call get_random_bytes_full
  is invoked which may sleep but offer access to the full functionality
  of the LRNG including all types of DRNG.

* use debugfs file for obtaining raw entropy test data required to fulfill
  SP800-90B requirements

* fix: ensure that gathering raw entropy does not affect runtime of the kernel

* fix: import upstream patch b7d5dc21072cda7124d13eae2aefb7343ef94197

* fix: import upstream patch 428826f5358c922dc378830a1717b682c0823160

* fix: integrate patch "random: Don't freeze in add_hwgenerator_randomness()
  if stopping kthread"

* documentation enhancement: import upstream patch
  92e507d216139b356a375afbda2824e85235e748 into documentation to cover all
  interfaces of the LRNG

* speedup of injection of non-aligned data into entropy pool

As a side node: With the switchable DRNG support offered in this patch set,
the following areas could be removed. As the existing /dev/random has no support
for switchable DRNGs, however, this is not yet feasible though.

* remove lrng_ready_list and all code around it in lrng_interfaces.c

* remove the kernel crypto API RNG API to avoid having two random number
  providing APIs - this would imply that all RNGs developed for this API would
  be converted to the LRNG interface

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>

Stephan Mueller (12):
  Linux Random Number Generator
  LRNG - allocate one SDRNG instance per NUMA node
  LRNG - /proc interface
  LRNG - add switchable DRNG support
  crypto: DRBG - externalize DRBG functions for LRNG
  LRNG - add SP800-90A DRBG extension
  LRNG - add kernel crypto API PRNG extension
  crypto: provide access to a static Jitter RNG state
  LRNG - add Jitter RNG fast noise source
  LRNG - add TRNG support
  LRNG - add SP800-90B compliance
  LRNG - add interface for gathering of raw entropy

 MAINTAINERS                         |   7 +
 crypto/drbg.c                       |  16 +-
 crypto/jitterentropy.c              |  23 +
 drivers/char/Kconfig                |   2 +
 drivers/char/Makefile               |   9 +-
 drivers/char/lrng/Kconfig           | 145 ++++++
 drivers/char/lrng/Makefile          |  19 +
 drivers/char/lrng/lrng_archrandom.c | 105 +++++
 drivers/char/lrng/lrng_aux.c        | 161 +++++++
 drivers/char/lrng/lrng_chacha20.c   | 341 ++++++++++++++
 drivers/char/lrng/lrng_drbg.c       | 274 +++++++++++
 drivers/char/lrng/lrng_health.c     | 424 ++++++++++++++++++
 drivers/char/lrng/lrng_interfaces.c | 648 ++++++++++++++++++++++++++
 drivers/char/lrng/lrng_internal.h   | 322 +++++++++++++
 drivers/char/lrng/lrng_jent.c       | 101 +++++
 drivers/char/lrng/lrng_kcapi.c      | 341 ++++++++++++++
 drivers/char/lrng/lrng_numa.c       | 114 +++++
 drivers/char/lrng/lrng_pool.c       | 673 ++++++++++++++++++++++++++++
 drivers/char/lrng/lrng_proc.c       | 192 ++++++++
 drivers/char/lrng/lrng_sdrng.c      | 458 +++++++++++++++++++
 drivers/char/lrng/lrng_sw_noise.c   | 156 +++++++
 drivers/char/lrng/lrng_switch.c     | 198 ++++++++
 drivers/char/lrng/lrng_testing.c    | 324 +++++++++++++
 drivers/char/lrng/lrng_trng.c       | 301 +++++++++++++
 include/crypto/drbg.h               |   7 +
 include/linux/lrng.h                |  83 ++++
 26 files changed, 5437 insertions(+), 7 deletions(-)
 create mode 100644 drivers/char/lrng/Kconfig
 create mode 100644 drivers/char/lrng/Makefile
 create mode 100644 drivers/char/lrng/lrng_archrandom.c
 create mode 100644 drivers/char/lrng/lrng_aux.c
 create mode 100644 drivers/char/lrng/lrng_chacha20.c
 create mode 100644 drivers/char/lrng/lrng_drbg.c
 create mode 100644 drivers/char/lrng/lrng_health.c
 create mode 100644 drivers/char/lrng/lrng_interfaces.c
 create mode 100644 drivers/char/lrng/lrng_internal.h
 create mode 100644 drivers/char/lrng/lrng_jent.c
 create mode 100644 drivers/char/lrng/lrng_kcapi.c
 create mode 100644 drivers/char/lrng/lrng_numa.c
 create mode 100644 drivers/char/lrng/lrng_pool.c
 create mode 100644 drivers/char/lrng/lrng_proc.c
 create mode 100644 drivers/char/lrng/lrng_sdrng.c
 create mode 100644 drivers/char/lrng/lrng_sw_noise.c
 create mode 100644 drivers/char/lrng/lrng_switch.c
 create mode 100644 drivers/char/lrng/lrng_testing.c
 create mode 100644 drivers/char/lrng/lrng_trng.c
 create mode 100644 include/linux/lrng.h

-- 
2.23.0





^ permalink raw reply	[flat|nested] 162+ messages in thread

* [PATCH v24 01/12] Linux Random Number Generator
  2019-11-11 18:17 [PATCH v24 00/12] /dev/random - a new approach with full SP800-90B compliance Stephan Müller
@ 2019-11-11 18:18 ` Stephan Müller
  2019-11-11 23:54   ` Thomas Gleixner
                     ` (3 more replies)
  2019-11-11 18:19 ` [PATCH v24 02/12] LRNG - allocate one SDRNG instance per NUMA node Stephan Müller
                   ` (13 subsequent siblings)
  14 siblings, 4 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-11 18:18 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

In an effort to provide a flexible implementation for a random number
generator that also delivers entropy during early boot time, allows
replacement of the deterministic random number generation mechanism,
implement the various components in separate code for easier
maintenance, and provide compliance to SP800-90[A|B|C], introduce
the Linux Random Number Generator (LRNG) framework.

The general design is as follows. Additional implementation details
are given in [1]. The LRNG consists of the following components:

1. The LRNG may contain a True Random Number Generator (TRNG). The
TRNG is a deterministic random number generator that is operated as
a true random number generator. Using SP800-90A terminology, the
TRNG is a DRBG with prediction resistance. The TRNG has a behavior
similar to SP800-90A's concept of prediction resistance by only
generating output when it is re-seeded with an equal amount of
entropy. Every time a caller requests random numbers, the TRNG
must be re-seeded with at least that amount of entropy from its noise
sources. During boot time, the TRNG is not yet operated with
prediction resistance. As the external interfaces to the TRNG to
obtain random numbers start to be accessible after boot time
completes, random numbers generated via these interfaces always
access the TRNG that is operated with prediction resistance.

2. The LRNG implements a secondary DRNG. The secondary DRNG always
generates the requested amount of output. When using the SP800-90A
terminology it operates without prediction resistance. The secondary
DRNG maintains a counter of how many bytes were generated since last
re-seed and a timer of the elapsed time since last re-seed. If either
the counter or the timer reaches a threshold, the secondary DRNG is
seeded from the TRNG.

In case the Linux kernel detects a NUMA system, one secondary DRNG
instance per NUMA node is maintained.

3. The TRNG is seeded by concatenating the data from the
following sources:

(a) the output of the entropy pool,

(b) the Jitter RNG if available and enabled, and

(c) the CPU-based noise source such as Intel RDRAND if available and
enabled.

The entropy estimate of the data of all noise sources are added to
form the entropy estimate of the data used to seed the TRNG with.
The LRNG ensures, however, that the TRNG after seeding is at
maximum the security strength of the TRNG.

The LRNG is designed such that none of these noise sources can dominate
the other noise sources to provide seed data to the TRNG during
boot time due to the following:

(a) During boot time, the amount of received interrupts are the trigger
points to (re)seed the TRNG.

(b) At runtime, the caller requesting random numbers from the primary
TRNG drives the reseeding where always as much entropy as available is
used to reseed the TRNG.

4. The entropy pool accumulates entropy obtained from certain events,
which will henceforth be collectively called "slow noise sources".
The entropy pool collects noise data from slow noise sources. Any data
received by the LRNG from the slow noise sources is inserted into the
entropy pool using an LFSR with a primitive and irreducible polynomial.
The following sources of entropy are used:

 (a) When an interrupt occurs, the high-resolution time stamp is mixed
into the LFSR. This time stamp is credited with heuristically implied
entropy.

 (b) HID event data like the key stroke or the mouse coordinates are
mixed into the LFSR. This data is not credited with entropy by the LRNG.

 (c) Device drivers may provide data that is mixed into the LFSR. This
data is not credited with entropy by the LRNG.

 (d) After the entropy pool is ``read'' by the TRNG, the data
used to seed the TRNG is mixed back into the entropy pool to
stir the pool. This data is not credited with entropy by the LRNG.

Any data provided from user space by either writing to /dev/random,
/dev/urandom or the IOCTL of RNDADDENTROPY on both device files
are always injected into the entropy pool.

In addition, when a hardware random number generator covered by the
Linux kernel HW generator framework wants to deliver random numbers,
it is injected into the entropy pool as well. HW generator noise source
is handled separately from the other noise source due to the fact that
the HW generator framework may decide by itself when to deliver data
whereas the other noise sources always requested for data driven by the
LRNG operation. Similarly any user space provided data is inserted into
the entropy pool.

When the TRNG requires data from the entropy pool, the entire
entropy pool is processed with an SP800-90A section 10.3.1 compliant
hash_df function to generate random numbers.

To speed up the interrupt handling code of the LRNG, the time stamp
collected for an interrupt event is truncated to the 8 least
significant bits. 64 truncated time stamps are concatenated and then
jointly inserted into the LFSR. During boot time, until the fully seeded
stage is reached, each time stamp with its 32 least significant bits is
inserted into the LFSR at the time of arrival.

The LRNG allows the TRNG and secondary DRNG mechanism to be changed
at runtime. Per default, a ChaCha20-based DRNG is used. The ChaCha20-DRNG
implemented for the LRNG is also provided as a stand-alone user space
deterministic random number generator. The LRNG also offers an
SP800-90A DRBG based on the Linux kernel crypto API DRBG implementation.

The DRNG allows two methods of obtaining random data:

* For users requiring random numbers from a seeded and frequently reseeded
secondary DRNG, such as the /dev/urandom, the getrandom system call or
the in-kernel get_random_bytes function, the secondary DRNG is accessed
directly by invoking its generate function. This generate function
complies with the generate function discussed in SP800-90A.

* Users requiring random data that contains information theoretical
entropy, such as for seeding other DRNGs also use the TRNG's
generate function via the /dev/random device file and the getrandom
system call when invoked with GRND_RANDOM. The difference to the
/dev/urandom handling is that:

 1. each TRNG generate request is limited to the amount of entropy
the of the DRNG was seeded with, and

 2. each TRNG generate request is preceded by a reseeding of the
DRNG to implement a TRNG / a DRNG with prediction resistance.

The processing of entropic data from the noise source before injecting
them into the TRNG is performed with the following mathematical
operations:

1. LFSR: The 8 least significant bits of the time stamp data received
from the interrupts are processed with an LFSR. That LFSR is implemented
identically to the LSFR used in the existing /dev/random implementation
except that it is capable of processing an entire word and that a
different polynomial is used. The reason for the different polynomial
is performance in a performance sensitive code section, the interrupt
handler. The chosen polynomials have 4 taps. Also, this LFSR-approach
is used in the OpenBSD /dev/random equivalent.

2. Concatenation: The temporary seed buffer used to seed the TRNG is
a concatenation of parts of the entropy pool data, and the CPU noise
source output.

The TRNG always tries to seed itself with 256 bits of entropy,
except during boot. In any case, if the noise sources cannot deliver
that amount, the available entropy is used and the TRNG keeps
track on how much entropy it was seeded with. The entropy implied by
the LRNG available in the entropy pool may be too conservative.
To ensure that during boot time all available entropy from the entropy
pool is transferred to the TRNG, the hash_df function always
generates 256 data bits during boot to seed the TRNG. Yet, the
TRNG entropy estimate is only increased by the amount of entropy the
LRNG assumes to be present in that data. During boot, the TRNG
is seeded as follows:

1. The DRNG is reseeded from the entropy pool and potentially the fast
noise sources if the entropy pool has collected at least 32 bits of
entropy from the interrupt noise source. The goal of this step is to
ensure that the primary and secondary DRNG receive some initial entropy
as early as possible. In addition it receives the entropy available from
the fast noise sources.

2. The DRNG is reseeded from the entropy pool and potentially the fast
noise sources if all noise sources collectively can provide at least
128 bits of entropy.

3. The DRNG is reseeded from the entropy pool and potentially the fast
noise sources if all noise sources collectivel can provide at least 256
bits.

At the time of the reseeding steps, the DRNG requests as much entropy as
is available in order to skip certain steps and reach the seeding level
of 256 bits. This may imply that one or more of the aforementioned steps
are skipped.

In all listed steps, the secondary DRNG is (re)seeded with a number of
random bytes from the TRNG that is equal to the amount of
entropy the TRNG was seeded with. This means that when the
TRNG is seeded with 128 or 256 bits of entropy, the secondary
DRNG is seeded with that amount of entropy as well. There is only one
exception to that rule: during initialization before the seed level of
128 bits is reached, a random number with 128 bit is generated by the
TRNG to seed the secondary DRNG.

Before the TRNG is seeded with 256 bits of entropy in step 3,
requests of random data from /dev/random are not processed.

At runtime, the TRNG delivers only random bytes equal to the
entropy amount it was seeded with. E.g. if the TRNG was seeded
with 128 bits of entropy, it will return only 128 bits of random data.
Subsequent requests for random data are only fulfilled after a
reseeding operation of the TRNG.

The TRNG will always require that all entropy sources collectively
can deliver at least as many entropy bits as configured with
/proc/sys/kernel/random/read_wakeup_threshold, i.e. per default 129 bits
(128 bits of entropy for seeding plus one bit of entropy that is lost
with the post processing as defined in SP800-90B).

The secondary DRNG operates as deterministic random number generator with
the following properties:

* The maximum number of random bytes that can be generated with one
DRNG generate operation is limited to 4096 bytes. When longer random
numbers are requested, multiple DRNG generate operations are performed.
The ChaCha20 DRNG as well as the SP800-90A DRBGs implement an update of
their state after completing a generate request for backtracking
resistance.

* The secondary DRNG is reseeded with whatever entropy is available –
in the worst case where no additional entropy can be provided by the
noise sources, the DRNG is not re-seeded and continues its operation
to try to reseed again after again the expiry of one of these thresholds:

 - If the last reseeding of the secondary DRNG is more than 600 seconds
   ago, or

 - 2^20 DRNG generate operations are performed, whatever comes first, or

 - the secondary DRNG is forced to reseed before the next generation of
   random numbers if data has been injected into the LRNG by writing data
   into /dev/random or /dev/urandom.

The chosen values prevent high-volume requests from user space to cause
frequent reseeding operations which drag down the performance of the
DRNG.

When the secondary DRNG requests a reseeding from the TRNG and
the TRNG pulls from the entropy pool, an emergency entropy level
of 512 bits of entropy is left in the entropy pool. This emergency
entropy is provided to serve /dev/random even while /dev/urandom is
stressed.

With the automatic reseeding after 600 seconds, the LRNG is triggered
to reseed itself before the first request after a suspend that put the
hardware to sleep for longer than 600 seconds.

The TRNG may not be compiled. In this case, the aforementioned
statements covering the TRNG are not applicable. The secondary DRNG is
seeded directly from the entropy pool just like the TRNG would have been
seeded.

The LRNG has the following properties:

* internal noise source: interrupts timing with fast boot time seeding

* 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().

* lockless LFSR to collect raw entropy

* use of standalone ChaCha20 based RNG with the option to use a
  different DRNG selectable at compile time

* "atomic" seeding of secondary DRBG to ensure full entropy transport

* instantiate one DRNG per NUMA node

* support for runtime switchable output DRNGs

* support for TRNG deactivation: The LRNG supports the compile-time
deactivation of the TRNG (i.e. the blocking behavior of /dev/random).
If deactivated, /dev/random operates like getrandom(2). This is
intended to cover the recent discussions about removing the
blocking_pool from the existing random.c.

* use of only well-defined entropy-preserving operations to collect,
compress and forward entropy: concatenation, LFSR, SP800-90A hash_df
function

* compile-time selectable entropy pool size: the choice also
uses the applicable LFSR polynomial to maintain the entropy pool
size

Further details including the rationale for the design choices and
properties of the LRNG together with testing is provided at [1].
In addition, the documentation explains the conducted regression
tests to verify that the LRNG is API and ABI compatible with the
existing /dev/random implementation.

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

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Mathematical aspects Reviewed-by: "Peter, Matthias" <matthias.peter@bsi.bund.de>
Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 MAINTAINERS                         |   7 +
 drivers/char/Kconfig                |   2 +
 drivers/char/Makefile               |   9 +-
 drivers/char/lrng/Kconfig           |  55 +++
 drivers/char/lrng/Makefile          |   9 +
 drivers/char/lrng/lrng_archrandom.c | 105 +++++
 drivers/char/lrng/lrng_aux.c        | 161 +++++++
 drivers/char/lrng/lrng_chacha20.c   | 341 ++++++++++++++
 drivers/char/lrng/lrng_interfaces.c | 649 +++++++++++++++++++++++++++
 drivers/char/lrng/lrng_internal.h   | 313 +++++++++++++
 drivers/char/lrng/lrng_pool.c       | 673 ++++++++++++++++++++++++++++
 drivers/char/lrng/lrng_sdrng.c      | 458 +++++++++++++++++++
 drivers/char/lrng/lrng_sw_noise.c   | 156 +++++++
 include/linux/lrng.h                |  83 ++++
 14 files changed, 3020 insertions(+), 1 deletion(-)
 create mode 100644 drivers/char/lrng/Kconfig
 create mode 100644 drivers/char/lrng/Makefile
 create mode 100644 drivers/char/lrng/lrng_archrandom.c
 create mode 100644 drivers/char/lrng/lrng_aux.c
 create mode 100644 drivers/char/lrng/lrng_chacha20.c
 create mode 100644 drivers/char/lrng/lrng_interfaces.c
 create mode 100644 drivers/char/lrng/lrng_internal.h
 create mode 100644 drivers/char/lrng/lrng_pool.c
 create mode 100644 drivers/char/lrng/lrng_sdrng.c
 create mode 100644 drivers/char/lrng/lrng_sw_noise.c
 create mode 100644 include/linux/lrng.h

diff --git a/MAINTAINERS b/MAINTAINERS
index cba1095547fd..7232989d3a1c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9488,6 +9488,13 @@ F:	Documentation/core-api/atomic_ops.rst
 F:	Documentation/core-api/refcount-vs-atomic.rst
 F:	Documentation/memory-barriers.txt
 
+LINUX RANDOM NUMBER GENERATOR (LRNG) DRIVER
+M:	Stephan Mueller <smueller@chronox.de>
+S:	Maintained
+W:	https://www.chronox.de/lrng.html
+F:	drivers/char/lrng/*
+F:	include/linux/lrng.h
+
 LIS3LV02D ACCELEROMETER DRIVER
 M:	Eric Piel <eric.piel@tremplin-utc.net>
 S:	Maintained
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index df0fc997dc3e..cebb3a62c2ca 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -535,6 +535,8 @@ config ADI
 	  and SSM (Silicon Secured Memory).  Intended consumers of this
 	  driver include crash and makedumpfile.
 
+source "drivers/char/lrng/Kconfig"
+
 endmenu
 
 config RANDOM_TRUST_CPU
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 7c5ea6f9df14..46ede09fd6d3 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -3,7 +3,14 @@
 # Makefile for the kernel character device drivers.
 #
 
-obj-y				+= mem.o random.o
+obj-y				+= mem.o
+
+ifeq ($(CONFIG_LRNG),y)
+  obj-y				+= lrng/
+else
+  obj-y				+= random.o
+endif
+
 obj-$(CONFIG_TTY_PRINTK)	+= ttyprintk.o
 obj-y				+= misc.o
 obj-$(CONFIG_ATARI_DSP56K)	+= dsp56k.o
diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
new file mode 100644
index 000000000000..edf8be6aa0b1
--- /dev/null
+++ b/drivers/char/lrng/Kconfig
@@ -0,0 +1,55 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Linux Random Number Generator configuration
+#
+
+menuconfig LRNG
+	bool "Linux Random Number Generator"
+	help
+	  The Linux Random Number Generator (LRNG) is the replacement
+	  of the existing /dev/random provided with drivers/char/random.c.
+	  It generates entropy from different noise sources and
+	  delivers significant entropy during boot.
+
+if LRNG
+
+choice
+	prompt "LRNG Entropy Pool Size"
+	default LRNG_POOL_SIZE_4096
+	help
+	  Select the size of the LRNG entropy pool. The size of the
+	  entropy pool is relevant for the amount of entropy that
+	  the LRNG can maintain as a maximum. The larger the size
+	  of the entropy pool is the more entropy can be maintained
+	  but the less often older entropic values are overwritten
+	  with new entropy.
+
+	config LRNG_POOL_SIZE_4096
+		bool "4096 bits (default)"
+
+	config LRNG_POOL_SIZE_8192
+		bool "8192 bits"
+
+	config LRNG_POOL_SIZE_16384
+		bool "16384 bits"
+
+	config LRNG_POOL_SIZE_32768
+		bool "32768 bits"
+
+	config LRNG_POOL_SIZE_65536
+		bool "65536 bits"
+
+	config LRNG_POOL_SIZE_131072
+		bool "131072 bits"
+endchoice
+
+config LRNG_POOL_SIZE
+	int
+	default 0 if LRNG_POOL_SIZE_4096
+	default 1 if LRNG_POOL_SIZE_8192
+	default 2 if LRNG_POOL_SIZE_16384
+	default 3 if LRNG_POOL_SIZE_32768
+	default 4 if LRNG_POOL_SIZE_65536
+	default 5 if LRNG_POOL_SIZE_131072
+
+endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
new file mode 100644
index 000000000000..2761623715d2
--- /dev/null
+++ b/drivers/char/lrng/Makefile
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for the Linux Random Number Generator.
+#
+
+obj-y				+= lrng_pool.o lrng_aux.o \
+				   lrng_sw_noise.o lrng_archrandom.o \
+				   lrng_sdrng.o lrng_chacha20.o \
+				   lrng_interfaces.o \
diff --git a/drivers/char/lrng/lrng_archrandom.c b/drivers/char/lrng/lrng_archrandom.c
new file mode 100644
index 000000000000..c448f4827794
--- /dev/null
+++ b/drivers/char/lrng/lrng_archrandom.c
@@ -0,0 +1,105 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG Fast Noise Source: CPU-based noise source
+ *
+ * Copyright (C) 2016 - 2019, Stephan Mueller <smueller@chronox.de>
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/random.h>
+
+#include "lrng_internal.h"
+
+/*
+ * Estimated entropy of data is a 32th of LRNG_DRNG_SECURITY_STRENGTH_BITS.
+ * As we have no ability to review the implementation of those noise sources,
+ * it is prudent to have a conservative estimate here.
+ */
+#define LRNG_ARCHRANDOM_DEFAULT_STRENGTH (LRNG_DRNG_SECURITY_STRENGTH_BITS>>5)
+#define LRNG_ARCHRANDOM_TRUST_CPU_STRENGTH LRNG_DRNG_SECURITY_STRENGTH_BITS
+#ifdef CONFIG_RANDOM_TRUST_CPU
+static u32 archrandom = LRNG_ARCHRANDOM_TRUST_CPU_STRENGTH;
+#else
+static u32 archrandom = LRNG_ARCHRANDOM_DEFAULT_STRENGTH;
+#endif
+module_param(archrandom, uint, 0644);
+MODULE_PARM_DESC(archrandom, "Entropy in bits of 256 data bits from CPU noise "
+			     "source (e.g. RDRAND)");
+
+static int __init lrng_parse_trust_cpu(char *arg)
+{
+	int ret;
+	bool trust_cpu = false;
+
+	ret = kstrtobool(arg, &trust_cpu);
+	if (ret)
+		return ret;
+
+	if (trust_cpu)
+		archrandom = LRNG_ARCHRANDOM_TRUST_CPU_STRENGTH;
+	else
+		archrandom = LRNG_ARCHRANDOM_DEFAULT_STRENGTH;
+
+	return 0;
+}
+early_param("random.trust_cpu", lrng_parse_trust_cpu);
+
+/**
+ * Get CPU noise source entropy
+ *
+ * @outbuf: buffer to store entropy of size LRNG_DRNG_SECURITY_STRENGTH_BYTES
+ * @return: > 0 on success where value provides the added entropy in bits
+ *	    0 if no fast source was available
+ */
+u32 lrng_get_arch(u8 *outbuf)
+{
+	u32 i, ent_bits = archrandom;
+
+	/* operate on full blocks */
+	BUILD_BUG_ON(LRNG_DRNG_SECURITY_STRENGTH_BYTES % sizeof(unsigned long));
+	/* ensure we have aligned buffers */
+	BUILD_BUG_ON(LRNG_KCAPI_ALIGN % sizeof(unsigned long));
+
+	if (!ent_bits)
+		return 0;
+
+	for (i = 0; i < LRNG_DRNG_SECURITY_STRENGTH_BYTES;
+	     i += sizeof(unsigned long)) {
+		if (!arch_get_random_seed_long((unsigned long *)(outbuf + i)) &&
+		    !arch_get_random_long((unsigned long *)(outbuf + i))) {
+			archrandom = 0;
+			return 0;
+		}
+	}
+
+	/* Obtain entropy statement -- cap entropy to buffer size in bits */
+	ent_bits = min_t(u32, ent_bits, LRNG_DRNG_SECURITY_STRENGTH_BITS);
+	pr_debug("obtained %u bits of entropy from CPU RNG noise source\n",
+		 ent_bits);
+	return ent_bits;
+}
+
+u32 lrng_slow_noise_req_entropy(u32 required_entropy_bits)
+{
+	u32 arch_ent_bits = min_t(u32, archrandom,
+				  LRNG_DRNG_SECURITY_STRENGTH_BITS);
+	u32 fast_noise_entropy = arch_ent_bits + lrng_jent_entropylevel();
+
+	if (fast_noise_entropy > required_entropy_bits)
+		return 0;
+	return (required_entropy_bits - fast_noise_entropy);
+}
diff --git a/drivers/char/lrng/lrng_aux.c b/drivers/char/lrng/lrng_aux.c
new file mode 100644
index 000000000000..28120b48e914
--- /dev/null
+++ b/drivers/char/lrng/lrng_aux.c
@@ -0,0 +1,161 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG auxiliary interfaces
+ *
+ * Copyright (C) 2019 Stephan Mueller <smueller@chronox.de>
+ * Copyright (C) 2017 Jason A. Donenfeld <Jason@zx2c4.com>. All
+ * Rights Reserved.
+ * Copyright (C) 2016 Jason Cooper <jason@lakedaemon.net>
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#include <linux/mm.h>
+#include <linux/random.h>
+
+#include "lrng_internal.h"
+
+struct batched_entropy {
+	union {
+		u64 entropy_u64[LRNG_DRNG_BLOCKSIZE / sizeof(u64)];
+		u32 entropy_u32[LRNG_DRNG_BLOCKSIZE / sizeof(u32)];
+	};
+	unsigned int position;
+	spinlock_t batch_lock;
+};
+
+/*
+ * Get a random word for internal kernel use only. The quality of the random
+ * number is either as good as RDRAND or as good as /dev/urandom, with the
+ * goal of being quite fast and not depleting entropy.
+ */
+static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_u64) = {
+	.batch_lock	= __SPIN_LOCK_UNLOCKED(batched_entropy_u64.lock),
+};
+
+u64 get_random_u64(void)
+{
+	u64 ret;
+	unsigned long flags;
+	struct batched_entropy *batch;
+
+#if BITS_PER_LONG == 64
+	if (arch_get_random_long((unsigned long *)&ret))
+		return ret;
+#else
+	if (arch_get_random_long((unsigned long *)&ret) &&
+	    arch_get_random_long((unsigned long *)&ret + 1))
+		return ret;
+#endif
+
+	lrng_debug_report_seedlevel("get_random_u64");
+
+	batch = raw_cpu_ptr(&batched_entropy_u64);
+	spin_lock_irqsave(&batch->batch_lock, flags);
+	if (batch->position % ARRAY_SIZE(batch->entropy_u64) == 0) {
+		lrng_sdrng_get_atomic((u8 *)batch->entropy_u64,
+				      LRNG_DRNG_BLOCKSIZE);
+		batch->position = 0;
+	}
+	ret = batch->entropy_u64[batch->position++];
+	spin_unlock_irqrestore(&batch->batch_lock, flags);
+	return ret;
+}
+EXPORT_SYMBOL(get_random_u64);
+
+static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_u32) = {
+	.batch_lock	= __SPIN_LOCK_UNLOCKED(batched_entropy_u32.lock),
+};
+
+u32 get_random_u32(void)
+{
+	u32 ret;
+	unsigned long flags;
+	struct batched_entropy *batch;
+
+	if (arch_get_random_int(&ret))
+		return ret;
+
+	lrng_debug_report_seedlevel("get_random_u32");
+
+	batch = raw_cpu_ptr(&batched_entropy_u32);
+	spin_lock_irqsave(&batch->batch_lock, flags);
+	if (batch->position % ARRAY_SIZE(batch->entropy_u32) == 0) {
+		lrng_sdrng_get_atomic((u8 *)batch->entropy_u32,
+				      LRNG_DRNG_BLOCKSIZE);
+		batch->position = 0;
+	}
+	ret = batch->entropy_u32[batch->position++];
+	spin_unlock_irqrestore(&batch->batch_lock, flags);
+	return ret;
+}
+EXPORT_SYMBOL(get_random_u32);
+
+/*
+ * It's important to invalidate all potential batched entropy that might
+ * be stored before the crng is initialized, which we can do lazily by
+ * simply resetting the counter to zero so that it's re-extracted on the
+ * next usage.
+ */
+void invalidate_batched_entropy(void)
+{
+	int cpu;
+	unsigned long flags;
+
+	for_each_possible_cpu(cpu) {
+		struct batched_entropy *batched_entropy;
+
+		batched_entropy = per_cpu_ptr(&batched_entropy_u32, cpu);
+		spin_lock_irqsave(&batched_entropy->batch_lock, flags);
+		batched_entropy->position = 0;
+		spin_unlock(&batched_entropy->batch_lock);
+
+		batched_entropy = per_cpu_ptr(&batched_entropy_u64, cpu);
+		spin_lock(&batched_entropy->batch_lock);
+		batched_entropy->position = 0;
+		spin_unlock_irqrestore(&batched_entropy->batch_lock, flags);
+	}
+}
+
+/**
+ * randomize_page - Generate a random, page aligned address
+ * @start:	The smallest acceptable address the caller will take.
+ * @range:	The size of the area, starting at @start, within which the
+ *		random address must fall.
+ *
+ * If @start + @range would overflow, @range is capped.
+ *
+ * NOTE: Historical use of randomize_range, which this replaces, presumed that
+ * @start was already page aligned.  We now align it regardless.
+ *
+ * Return: A page aligned address within [start, start + range).  On error,
+ * @start is returned.
+ */
+unsigned long randomize_page(unsigned long start, unsigned long range)
+{
+	if (!PAGE_ALIGNED(start)) {
+		range -= PAGE_ALIGN(start) - start;
+		start = PAGE_ALIGN(start);
+	}
+
+	if (start > ULONG_MAX - range)
+		range = ULONG_MAX - start;
+
+	range >>= PAGE_SHIFT;
+
+	if (range == 0)
+		return start;
+
+	return start + (get_random_long() % range << PAGE_SHIFT);
+}
diff --git a/drivers/char/lrng/lrng_chacha20.c b/drivers/char/lrng/lrng_chacha20.c
new file mode 100644
index 000000000000..aa8121fe88db
--- /dev/null
+++ b/drivers/char/lrng/lrng_chacha20.c
@@ -0,0 +1,341 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * Backend for the LRNG providing the cryptographic primitives using
+ * ChaCha20 cipher implementations.
+ *
+ * Copyright (C) 2016 - 2019, Stephan Mueller <smueller@chronox.de>
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <crypto/chacha.h>
+#include <linux/cryptohash.h>
+#include <linux/lrng.h>
+#include <linux/random.h>
+
+#include "lrng_internal.h"
+
+/******************************* ChaCha20 DRNG *******************************/
+
+/* State according to RFC 7539 section 2.3 */
+struct chacha20_block {
+	u32 constants[4];
+#define CHACHA_KEY_SIZE_WORDS (CHACHA_KEY_SIZE / sizeof(u32))
+	union {
+		u32 u[CHACHA_KEY_SIZE_WORDS];
+		u8  b[CHACHA_KEY_SIZE];
+	} key;
+	u32 counter;
+	u32 nonce[3];
+};
+
+#define CHACHA_BLOCK_WORDS	(CHACHA_BLOCK_SIZE / sizeof(u32))
+
+struct chacha20_state {
+	struct chacha20_block block;
+};
+
+/*
+ * Have two static memory blocks for two ChaCha20 DRNG instances (the primary
+ * and the secondary DRNG) to avoid calling kmalloc too early in the boot cycle.
+ * for subsequent allocation requests, such as per-NUMA-node DRNG instances,
+ * kmalloc will be used.
+ */
+struct chacha20_state primary_chacha20;
+struct chacha20_state secondary_chacha20;
+
+/**
+ * Update of the ChaCha20 state by either using an unused buffer part or by
+ * generating one ChaCha20 block which is half of the state of the ChaCha20.
+ * The block is XORed into the key part of the state. This shall ensure
+ * backtracking resistance as well as a proper mix of the ChaCha20 state once
+ * the key is injected.
+ */
+static void lrng_chacha20_update(struct chacha20_state *chacha20_state,
+				 u32 *buf, u32 used_words)
+{
+	struct chacha20_block *chacha20 = &chacha20_state->block;
+	u32 i, tmp[CHACHA_BLOCK_WORDS];
+
+	BUILD_BUG_ON(sizeof(struct chacha20_block) != CHACHA_BLOCK_SIZE);
+	BUILD_BUG_ON(CHACHA_BLOCK_SIZE != 2 * CHACHA_KEY_SIZE);
+
+	if (used_words > CHACHA_KEY_SIZE_WORDS) {
+		chacha20_block(&chacha20->constants[0], (u8 *)tmp);
+		for (i = 0; i < CHACHA_KEY_SIZE_WORDS; i++)
+			chacha20->key.u[i] ^= tmp[i];
+		memzero_explicit(tmp, sizeof(tmp));
+	} else {
+		for (i = 0; i < CHACHA_KEY_SIZE_WORDS; i++)
+			chacha20->key.u[i] ^= buf[i + used_words];
+	}
+
+	/* Deterministic increment of nonce as required in RFC 7539 chapter 4 */
+	chacha20->nonce[0]++;
+	if (chacha20->nonce[0] == 0)
+		chacha20->nonce[1]++;
+	if (chacha20->nonce[1] == 0)
+		chacha20->nonce[2]++;
+
+	/* Leave counter untouched as it is start value is undefined in RFC */
+}
+
+/**
+ * Seed the ChaCha20 DRNG by injecting the input data into the key part of
+ * the ChaCha20 state. If the input data is longer than the ChaCha20 key size,
+ * perform a ChaCha20 operation after processing of key size input data.
+ * This operation shall spread out the entropy into the ChaCha20 state before
+ * new entropy is injected into the key part.
+ */
+static int lrng_cc20_drng_seed_helper(void *drng, const u8 *inbuf, u32 inbuflen)
+{
+	struct chacha20_state *chacha20_state = (struct chacha20_state *)drng;
+	struct chacha20_block *chacha20 = &chacha20_state->block;
+
+	while (inbuflen) {
+		u32 i, todo = min_t(u32, inbuflen, CHACHA_KEY_SIZE);
+
+		for (i = 0; i < todo; i++)
+			chacha20->key.b[i] ^= inbuf[i];
+
+		/* Break potential dependencies between the inbuf key blocks */
+		lrng_chacha20_update(chacha20_state, NULL,
+				     CHACHA_BLOCK_WORDS);
+		inbuf += todo;
+		inbuflen -= todo;
+	}
+
+	return 0;
+}
+
+/**
+ * Chacha20 DRNG generation of random numbers: the stream output of ChaCha20
+ * is the random number. After the completion of the generation of the
+ * stream, the entire ChaCha20 state is updated.
+ *
+ * Note, as the ChaCha20 implements a 32 bit counter, we must ensure
+ * that this function is only invoked for at most 2^32 - 1 ChaCha20 blocks
+ * before a reseed or an update happens. This is ensured by the variable
+ * outbuflen which is a 32 bit integer defining the number of bytes to be
+ * generated by the ChaCha20 DRNG. At the end of this function, an update
+ * operation is invoked which implies that the 32 bit counter will never be
+ * overflown in this implementation.
+ */
+static int lrng_cc20_drng_generate_helper(void *drng, u8 *outbuf, u32 outbuflen)
+{
+	struct chacha20_state *chacha20_state = (struct chacha20_state *)drng;
+	struct chacha20_block *chacha20 = &chacha20_state->block;
+	u32 aligned_buf[CHACHA_BLOCK_WORDS], ret = outbuflen,
+	    used = CHACHA_BLOCK_WORDS;
+	int zeroize_buf = 0;
+
+	while (outbuflen >= CHACHA_BLOCK_SIZE) {
+		chacha20_block(&chacha20->constants[0], outbuf);
+		outbuf += CHACHA_BLOCK_SIZE;
+		outbuflen -= CHACHA_BLOCK_SIZE;
+	}
+
+	if (outbuflen) {
+		chacha20_block(&chacha20->constants[0], (u8 *)aligned_buf);
+		memcpy(outbuf, aligned_buf, outbuflen);
+		used = ((outbuflen + sizeof(aligned_buf[0]) - 1) /
+			sizeof(aligned_buf[0]));
+		zeroize_buf = 1;
+	}
+
+	lrng_chacha20_update(chacha20_state, aligned_buf, used);
+
+	if (zeroize_buf)
+		memzero_explicit(aligned_buf, sizeof(aligned_buf));
+
+	return ret;
+}
+
+/**
+ * ChaCha20 DRNG that provides full strength, i.e. the output is capable
+ * of transporting 1 bit of entropy per data bit, provided the DRNG was
+ * seeded with 256 bits of entropy. This is achieved by folding the ChaCha20
+ * block output of 512 bits in half using XOR.
+ *
+ * Other than the output handling, the implementation is conceptually
+ * identical to lrng_drng_generate_helper.
+ */
+static int lrng_cc20_drng_generate_helper_full(void *drng, u8 *outbuf,
+					       u32 outbuflen)
+{
+	struct chacha20_state *chacha20_state = (struct chacha20_state *)drng;
+	struct chacha20_block *chacha20 = &chacha20_state->block;
+	u32 aligned_buf[CHACHA_BLOCK_WORDS];
+	u32 ret = outbuflen;
+
+	while (outbuflen >= CHACHA_BLOCK_SIZE) {
+		u32 i;
+
+		chacha20_block(&chacha20->constants[0], outbuf);
+
+		/* fold output in half */
+		for (i = 0; i < (CHACHA_BLOCK_WORDS / 2); i++)
+			outbuf[i] ^= outbuf[i + (CHACHA_BLOCK_WORDS / 2)];
+
+		outbuf += CHACHA_BLOCK_SIZE / 2;
+		outbuflen -= CHACHA_BLOCK_SIZE / 2;
+	}
+
+	while (outbuflen) {
+		u32 i, todo = min_t(u32, CHACHA_BLOCK_SIZE / 2, outbuflen);
+
+		chacha20_block(&chacha20->constants[0], (u8 *)aligned_buf);
+
+		/* fold output in half */
+		for (i = 0; i < (CHACHA_BLOCK_WORDS / 2); i++)
+			aligned_buf[i] ^=
+				aligned_buf[i + (CHACHA_BLOCK_WORDS / 2)];
+
+		memcpy(outbuf, aligned_buf, todo);
+		outbuflen -= todo;
+		outbuf += todo;
+	}
+	memzero_explicit(aligned_buf, sizeof(aligned_buf));
+
+	lrng_chacha20_update(chacha20_state, NULL, CHACHA_BLOCK_WORDS);
+
+	return ret;
+}
+
+void lrng_cc20_init_state(struct chacha20_state *state)
+{
+	struct chacha20_block *chacha20 = &state->block;
+	unsigned long v;
+	u32 i;
+
+	memcpy(&chacha20->constants[0], "expand 32-byte k", 16);
+
+	for (i = 0; i < CHACHA_KEY_SIZE_WORDS; i++) {
+		chacha20->key.u[i] ^= jiffies;
+		chacha20->key.u[i] ^= random_get_entropy();
+		if (arch_get_random_seed_long(&v) || arch_get_random_long(&v))
+			chacha20->key.u[i] ^= v;
+	}
+
+	for (i = 0; i < 3; i++) {
+		chacha20->nonce[i] ^= jiffies;
+		chacha20->nonce[i] ^= random_get_entropy();
+		if (arch_get_random_seed_long(&v) || arch_get_random_long(&v))
+			chacha20->nonce[i] ^= v;
+	}
+
+	pr_info("ChaCha20 core initialized\n");
+}
+
+/**
+ * Allocation of the DRNG state
+ */
+static void *lrng_cc20_drng_alloc(u32 sec_strength)
+{
+	struct chacha20_state *state = NULL;
+
+	if (sec_strength > CHACHA_KEY_SIZE) {
+		pr_err("Security strength of ChaCha20 DRNG (%u bits) lower "
+		       "than requested by LRNG (%u bits)\n",
+			CHACHA_KEY_SIZE * 8, sec_strength * 8);
+		return ERR_PTR(-EINVAL);
+	}
+	if (sec_strength < CHACHA_KEY_SIZE)
+		pr_warn("Security strength of ChaCha20 DRNG (%u bits) higher "
+			"than requested by LRNG (%u bits)\n",
+			CHACHA_KEY_SIZE * 8, sec_strength * 8);
+
+	state = kmalloc(sizeof(struct chacha20_state), GFP_KERNEL);
+	if (!state)
+		return ERR_PTR(-ENOMEM);
+	pr_debug("memory for ChaCha20 core allocated\n");
+
+	lrng_cc20_init_state(state);
+
+	return state;
+}
+
+static void lrng_cc20_drng_dealloc(void *drng)
+{
+	struct chacha20_state *chacha20_state = (struct chacha20_state *)drng;
+
+	if (drng == &primary_chacha20 || drng == &secondary_chacha20) {
+		memzero_explicit(chacha20_state, sizeof(*chacha20_state));
+		pr_debug("static ChaCha20 core zeroized\n");
+		return;
+	}
+
+	pr_debug("ChaCha20 core zeroized and freed\n");
+	kzfree(chacha20_state);
+}
+
+/******************************* Hash Operation *******************************/
+
+static void *lrng_cc20_hash_alloc(const u8 *key, u32 keylen)
+{
+	pr_info("Hash SHA-1 allocated\n");
+	return NULL;
+}
+
+static void lrng_cc20_hash_dealloc(void *hash)
+{
+}
+
+static u32 lrng_cc20_hash_digestsize(void *hash)
+{
+	return (SHA_DIGEST_WORDS * sizeof(u32));
+}
+
+static int lrng_cc20_hash_buffer(void *hash, const u8 *inbuf, u32 inbuflen,
+				 u8 *digest)
+{
+	u32 i;
+	u32 workspace[SHA_WORKSPACE_WORDS];
+
+	WARN_ON(inbuflen % (SHA_WORKSPACE_WORDS * sizeof(u32)));
+
+	for (i = 0; i < inbuflen; i += (SHA_WORKSPACE_WORDS * sizeof(u32)))
+		sha_transform((u32 *)digest, (inbuf + i), workspace);
+	memzero_explicit(workspace, sizeof(workspace));
+
+	return 0;
+}
+
+static const char *lrng_cc20_drng_name(void)
+{
+	const char *cc20_drng_name = "ChaCha20 DRNG";
+	return cc20_drng_name;
+}
+
+static const char *lrng_cc20_hash_name(void)
+{
+	const char *cc20_hash_name = "SHA-1";
+	return cc20_hash_name;
+}
+
+const struct lrng_crypto_cb lrng_cc20_crypto_cb = {
+	.lrng_drng_name			= lrng_cc20_drng_name,
+	.lrng_hash_name			= lrng_cc20_hash_name,
+	.lrng_drng_alloc		= lrng_cc20_drng_alloc,
+	.lrng_drng_dealloc		= lrng_cc20_drng_dealloc,
+	.lrng_drng_seed_helper		= lrng_cc20_drng_seed_helper,
+	.lrng_drng_generate_helper	= lrng_cc20_drng_generate_helper,
+	.lrng_drng_generate_helper_full	= lrng_cc20_drng_generate_helper_full,
+	.lrng_hash_alloc		= lrng_cc20_hash_alloc,
+	.lrng_hash_dealloc		= lrng_cc20_hash_dealloc,
+	.lrng_hash_digestsize		= lrng_cc20_hash_digestsize,
+	.lrng_hash_buffer		= lrng_cc20_hash_buffer,
+};
diff --git a/drivers/char/lrng/lrng_interfaces.c b/drivers/char/lrng/lrng_interfaces.c
new file mode 100644
index 000000000000..e652849a1bdb
--- /dev/null
+++ b/drivers/char/lrng/lrng_interfaces.c
@@ -0,0 +1,649 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG User and kernel space interfaces
+ *
+ * Copyright (C) 2016 - 2019, Stephan Mueller <smueller@chronox.de>
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/freezer.h>
+#include <linux/fs.h>
+#include <linux/genhd.h>
+#include <linux/kthread.h>
+#include <linux/poll.h>
+#include <linux/preempt.h>
+#include <linux/random.h>
+#include <linux/slab.h>
+#include <linux/syscalls.h>
+#include <linux/timex.h>
+
+#include "lrng_internal.h"
+
+/*
+ * The minimum number of bits of entropy before we wake up a read on
+ * /dev/random.
+ */
+u32 lrng_read_wakeup_bits = LRNG_MIN_SEED_ENTROPY_BITS +
+			    LRNG_CONDITIONING_ENTROPY_LOSS;
+
+/*
+ * If the entropy count falls under this number of bits, then we
+ * should wake up processes which are selecting or polling on write
+ * access to /dev/random.
+ */
+u32 lrng_write_wakeup_bits = LRNG_EMERG_ENTROPY +
+			     2 * LRNG_DRNG_SECURITY_STRENGTH_BITS;
+
+static LIST_HEAD(lrng_ready_list);
+static DEFINE_SPINLOCK(lrng_ready_list_lock);
+
+static DECLARE_WAIT_QUEUE_HEAD(lrng_read_wait);
+static DECLARE_WAIT_QUEUE_HEAD(lrng_write_wait);
+static DECLARE_WAIT_QUEUE_HEAD(lrng_init_wait);
+static struct fasync_struct *fasync;
+
+struct ctl_table random_table[];
+/********************************** Helper ***********************************/
+
+/* Is the primary DRNG seed level too low? */
+static inline bool lrng_need_entropy(void)
+{
+	return (lrng_avail_entropy() < lrng_write_wakeup_bits);
+}
+
+/* Is the entropy pool filled for /dev/random pull or DRNG fully seeded? */
+static inline bool lrng_have_entropy_full(void)
+{
+	return (lrng_avail_entropy() >= lrng_read_wakeup_bits);
+}
+
+void lrng_reader_wakeup(void)
+{
+	if (lrng_have_entropy_full() && wq_has_sleeper(&lrng_read_wait)) {
+		wake_up_interruptible(&lrng_read_wait);
+		kill_fasync(&fasync, SIGIO, POLL_IN);
+	}
+}
+
+void lrng_writer_wakeup(void)
+{
+	if (lrng_need_entropy() && wq_has_sleeper(&lrng_write_wait)) {
+		wake_up_interruptible(&lrng_write_wait);
+		kill_fasync(&fasync, SIGIO, POLL_OUT);
+	}
+}
+
+void lrng_init_wakeup(void)
+{
+	wake_up_all(&lrng_init_wait);
+}
+
+/**
+ * Ping all kernel internal callers waiting until the DRNG is fully
+ * seeded that the DRNG is now fully seeded.
+ *
+ * When the SP800-90B testing is enabled, the ping only happens if the SP800-90B
+ * startup health tests are completed. This implies that kernel internal
+ * callers always have an SP800-90B compliant noise source when being
+ * pinged.
+ */
+void lrng_process_ready_list(void)
+{
+	unsigned long flags;
+	struct random_ready_callback *rdy, *tmp;
+
+	if (!lrng_sp80090b_startup_complete())
+		return;
+
+	spin_lock_irqsave(&lrng_ready_list_lock, flags);
+	list_for_each_entry_safe(rdy, tmp, &lrng_ready_list, list) {
+		struct module *owner = rdy->owner;
+
+		list_del_init(&rdy->list);
+		rdy->func(rdy);
+		module_put(owner);
+	}
+	spin_unlock_irqrestore(&lrng_ready_list_lock, flags);
+}
+
+void lrng_debug_report_seedlevel(const char *name)
+{
+#ifdef CONFIG_WARN_ALL_UNSEEDED_RANDOM
+	static void *previous = NULL;
+	void *caller = (void *) _RET_IP_;
+
+	if (READ_ONCE(previous) == caller)
+		return;
+
+	if (!lrng_state_min_seeded())
+		pr_notice("%pS %s called without reaching mimimally seeded "
+			  "level (available entropy %u)\n", caller, name,
+			  lrng_avail_entropy());
+
+	WRITE_ONCE(previous, caller);
+#endif
+}
+
+/************************ LRNG kernel input interfaces ************************/
+
+/**
+ * Interface for in-kernel drivers of true hardware RNGs.
+ * Those devices may produce endless random bits and will be throttled
+ * when our pool is full.
+ *
+ * @buffer: buffer holding the entropic data from HW noise sources to be used to
+ *	    (re)seed the DRNG.
+ * @count: length of buffer
+ * @entropy_bits: amount of entropy in buffer (value is in bits)
+ */
+void add_hwgenerator_randomness(const char *buffer, size_t count,
+				size_t entropy_bits)
+{
+	/* DRNG is not yet online */
+	if (!lrng_get_available())
+		return;
+	/*
+	 * Suspend writing if we are fully loaded with entropy.
+	 * We'll be woken up again once below lrng_write_wakeup_thresh,
+	 * or when the calling thread is about to terminate.
+	 */
+	wait_event_interruptible(lrng_write_wait, lrng_need_entropy() ||
+						  kthread_should_stop() ||
+						  freezing(current));
+	lrng_pool_lfsr_nonaligned(buffer, count);
+	lrng_pool_add_entropy(entropy_bits);
+}
+EXPORT_SYMBOL_GPL(add_hwgenerator_randomness);
+
+/* Handle random seed passed by bootloader.
+ * If the seed is trustworthy, it would be regarded as hardware RNGs. Otherwise
+ * it would be regarded as device data.
+ * The decision is controlled by CONFIG_RANDOM_TRUST_BOOTLOADER.
+ */
+void add_bootloader_randomness(const void *buf, unsigned int size)
+{
+	if (IS_ENABLED(CONFIG_RANDOM_TRUST_BOOTLOADER))
+		add_hwgenerator_randomness(buf, size, size * 8);
+	else
+		add_device_randomness(buf, size);
+}
+EXPORT_SYMBOL_GPL(add_bootloader_randomness);
+
+/**
+ * Callback for HID layer -- use the HID event values to stir the entropy pool
+ */
+void add_input_randomness(unsigned int type, unsigned int code,
+			  unsigned int value)
+{
+	static unsigned char last_value;
+
+	/* ignore autorepeat and the like */
+	if (value == last_value)
+		return;
+
+	last_value = value;
+
+	lrng_pool_lfsr_u32((type << 4) ^ code ^ (code >> 4) ^ value);
+}
+EXPORT_SYMBOL_GPL(add_input_randomness);
+
+/*
+ * Add device- or boot-specific data to the input pool to help
+ * initialize it.
+ *
+ * None of this adds any entropy; it is meant to avoid the problem of
+ * the entropy pool having similar initial state across largely
+ * identical devices.
+ */
+void add_device_randomness(const void *buf, unsigned int size)
+{
+	lrng_pool_lfsr_nonaligned((u8 *)buf, size);
+	lrng_pool_lfsr_u32(random_get_entropy());
+	lrng_pool_lfsr_u32(jiffies);
+}
+EXPORT_SYMBOL(add_device_randomness);
+
+#ifdef CONFIG_BLOCK
+void rand_initialize_disk(struct gendisk *disk) { }
+void add_disk_randomness(struct gendisk *disk) { }
+EXPORT_SYMBOL(add_disk_randomness);
+#endif
+
+/**
+ * Delete a previously registered readiness callback function.
+ */
+void del_random_ready_callback(struct random_ready_callback *rdy)
+{
+	unsigned long flags;
+	struct module *owner = NULL;
+
+	spin_lock_irqsave(&lrng_ready_list_lock, flags);
+	if (!list_empty(&rdy->list)) {
+		list_del_init(&rdy->list);
+		owner = rdy->owner;
+	}
+	spin_unlock_irqrestore(&lrng_ready_list_lock, flags);
+
+	module_put(owner);
+}
+EXPORT_SYMBOL(del_random_ready_callback);
+
+/**
+ * Add a callback function that will be invoked when the DRNG is fully seeded.
+ *
+ * @return: 0 if callback is successfully added
+ *          -EALREADY if pool is already initialised (callback not called)
+ *	    -ENOENT if module for callback is not alive
+ */
+int add_random_ready_callback(struct random_ready_callback *rdy)
+{
+	struct module *owner;
+	unsigned long flags;
+	int err = -EALREADY;
+
+	if (likely(lrng_state_min_seeded()))
+		return err;
+
+	owner = rdy->owner;
+	if (!try_module_get(owner))
+		return -ENOENT;
+
+	spin_lock_irqsave(&lrng_ready_list_lock, flags);
+	if (lrng_state_min_seeded())
+		goto out;
+
+	owner = NULL;
+
+	list_add(&rdy->list, &lrng_ready_list);
+	err = 0;
+
+out:
+	spin_unlock_irqrestore(&lrng_ready_list_lock, flags);
+
+	module_put(owner);
+
+	return err;
+}
+EXPORT_SYMBOL(add_random_ready_callback);
+
+/*********************** LRNG kernel output interfaces ************************/
+
+/**
+ * Provider of cryptographic strong random numbers for kernel-internal usage.
+ * This function is appropriate for all in-kernel use cases. However,
+ * it will always use the ChaCha20 DRNG.
+ *
+ * @buf: buffer to store the random bytes
+ * @nbytes: size of the buffer
+ */
+void get_random_bytes(void *buf, int nbytes)
+{
+	lrng_sdrng_get_atomic((u8 *)buf, (u32)nbytes);
+	lrng_debug_report_seedlevel("get_random_bytes");
+}
+EXPORT_SYMBOL(get_random_bytes);
+
+/**
+ * Provider of cryptographic strong random numbers for kernel-internal usage.
+ * This function is appropriate only for non-atomic use cases as this
+ * function may sleep. Though, it provides access to the full functionality
+ * of LRNG including the switchable DRNG support, that may support other
+ * DRNGs such as the SP800-90A DRBG.
+ *
+ * @buf: buffer to store the random bytes
+ * @nbytes: size of the buffer
+ */
+void get_random_bytes_full(void *buf, int nbytes)
+{
+	lrng_sdrng_get_sleep((u8 *)buf, (u32)nbytes);
+	lrng_debug_report_seedlevel("get_random_bytes_full");
+}
+EXPORT_SYMBOL(get_random_bytes_full);
+
+/**
+ * Wait for the LRNG to be seeded and thus guaranteed to supply
+ * cryptographically secure random numbers. This applies to: the /dev/urandom
+ * device, the get_random_bytes function, and the get_random_{u32,u64,int,long}
+ * family of functions. Using any of these functions without first calling
+ * this function forfeits the guarantee of security.
+ *
+ * Returns: 0 if the LRNG has been seeded.
+ *          -ERESTARTSYS if the function was interrupted by a signal.
+ */
+int wait_for_random_bytes(void)
+{
+	if (likely(lrng_state_min_seeded()))
+		return 0;
+	return wait_event_interruptible(lrng_init_wait,
+					lrng_state_min_seeded());
+}
+EXPORT_SYMBOL(wait_for_random_bytes);
+
+/**
+ * This function will use the architecture-specific hardware random
+ * number generator if it is available.  The arch-specific hw RNG will
+ * almost certainly be faster than what we can do in software, but it
+ * is impossible to verify that it is implemented securely (as
+ * opposed, to, say, the AES encryption of a sequence number using a
+ * key known by the NSA).  So it's useful if we need the speed, but
+ * only if we're willing to trust the hardware manufacturer not to
+ * have put in a back door.
+ *
+ * @buf: buffer allocated by caller to store the random data in
+ * @nbytes: length of outbuf
+ *
+ * Return number of bytes filled in.
+ */
+int __must_check get_random_bytes_arch(void *buf, int nbytes)
+{
+	u8 *p = buf;
+
+	while (nbytes) {
+		unsigned long v;
+		int chunk = min_t(int, nbytes, sizeof(unsigned long));
+
+		if (!arch_get_random_long(&v))
+			break;
+
+		memcpy(p, &v, chunk);
+		p += chunk;
+		nbytes -= chunk;
+	}
+
+	if (nbytes)
+		lrng_sdrng_get_atomic((u8 *)p, (u32)nbytes);
+
+	return nbytes;
+}
+EXPORT_SYMBOL(get_random_bytes_arch);
+
+/************************ LRNG user output interfaces *************************/
+
+static ssize_t lrng_read_common(char __user *buf, size_t nbytes,
+			int (*lrng_read_random)(u8 *outbuf, u32 outbuflen))
+{
+	ssize_t ret = 0;
+	u8 tmpbuf[LRNG_DRNG_BLOCKSIZE] __aligned(LRNG_KCAPI_ALIGN);
+	u8 *tmp_large = NULL, *tmp = tmpbuf;
+	u32 tmplen = sizeof(tmpbuf);
+
+	if (nbytes == 0)
+		return 0;
+
+	/*
+	 * Satisfy large read requests -- as the common case are smaller
+	 * request sizes, such as 16 or 32 bytes, avoid a kmalloc overhead for
+	 * those by using the stack variable of tmpbuf.
+	 */
+	if (nbytes > sizeof(tmpbuf)) {
+		tmplen = min_t(u32, nbytes, LRNG_DRNG_MAX_REQSIZE);
+		tmp_large = kmalloc(tmplen + LRNG_KCAPI_ALIGN, GFP_KERNEL);
+		if (!tmp_large)
+			tmplen = sizeof(tmpbuf);
+		else
+			tmp = PTR_ALIGN(tmp_large, LRNG_KCAPI_ALIGN);
+	}
+
+	while (nbytes) {
+		u32 todo = min_t(u32, nbytes, tmplen);
+		int rc = 0;
+
+		/* Reschedule if we received a large request. */
+		if ((tmp_large) && need_resched()) {
+			if (signal_pending(current)) {
+				if (ret == 0)
+					ret = -ERESTARTSYS;
+				break;
+			}
+			schedule();
+		}
+
+		rc = lrng_read_random(tmp, todo);
+		if (rc <= 0) {
+			if (rc < 0)
+				ret = rc;
+			break;
+		}
+		if (copy_to_user(buf, tmp, rc)) {
+			ret = -EFAULT;
+			break;
+		}
+
+		nbytes -= rc;
+		buf += rc;
+		ret += rc;
+	}
+
+	/* Wipe data just returned from memory */
+	if (tmp_large)
+		kzfree(tmp_large);
+	else
+		memzero_explicit(tmpbuf, sizeof(tmpbuf));
+
+	return ret;
+}
+
+static ssize_t
+lrng_trng_read_common(int nonblock, char __user *buf, size_t nbytes)
+{
+	if (nbytes == 0)
+		return 0;
+
+	nbytes = min_t(u32, nbytes, LRNG_DRNG_BLOCKSIZE);
+	while (1) {
+		ssize_t n = lrng_read_common(buf, nbytes, lrng_trng_get);
+
+		if (n)
+			return n;
+
+		/* No entropy available.  Maybe wait and retry. */
+		if (nonblock)
+			return -EAGAIN;
+
+		wait_event_interruptible(lrng_read_wait,
+					 lrng_have_entropy_full());
+		if (signal_pending(current))
+			return -ERESTARTSYS;
+	}
+}
+
+static ssize_t lrng_trng_read(struct file *file, char __user *buf,
+			      size_t nbytes, loff_t *ppos)
+{
+	return lrng_trng_read_common(file->f_flags & O_NONBLOCK, buf, nbytes);
+}
+
+static unsigned int lrng_trng_poll(struct file *file, poll_table *wait)
+{
+	__poll_t mask;
+
+	poll_wait(file, &lrng_read_wait, wait);
+	poll_wait(file, &lrng_write_wait, wait);
+	mask = 0;
+	if (lrng_have_entropy_full())
+		mask |= EPOLLIN | EPOLLRDNORM;
+	if (lrng_need_entropy())
+		mask |= EPOLLOUT | EPOLLWRNORM;
+	return mask;
+}
+
+static ssize_t lrng_drng_write_common(const char __user *buffer, size_t count,
+				      u32 entropy_bits)
+{
+	ssize_t ret = 0;
+	u8 buf[64] __aligned(LRNG_KCAPI_ALIGN);
+	const char __user *p = buffer;
+	u32 orig_entropy_bits = entropy_bits;
+
+	if (!lrng_get_available())
+		return -EAGAIN;
+
+	count = min_t(size_t, count, INT_MAX);
+	while (count > 0) {
+		size_t bytes = min_t(size_t, count, sizeof(buf));
+		u32 ent = min_t(u32, bytes<<3, entropy_bits);
+
+		if (copy_from_user(&buf, p, bytes))
+			return -EFAULT;
+		/* Inject data into entropy pool */
+		lrng_pool_lfsr(buf, bytes);
+		lrng_pool_add_entropy(ent);
+
+		count -= bytes;
+		p += bytes;
+		ret += bytes;
+		entropy_bits -= ent;
+
+		cond_resched();
+	}
+
+	/* Force reseed of secondary DRNG during next data request. */
+	if (!orig_entropy_bits)
+		lrng_sdrng_force_reseed();
+
+	return ret;
+}
+
+static ssize_t lrng_sdrng_read(struct file *file, char __user *buf,
+			       size_t nbytes, loff_t *ppos)
+{
+	if (!lrng_state_min_seeded())
+		pr_notice_ratelimited("%s - use of insufficiently seeded DRNG "
+				      "(%zu bytes read)\n", current->comm,
+				      nbytes);
+	else if (!lrng_state_operational())
+		pr_debug_ratelimited("%s - use of not fully seeded DRNG (%zu "
+				     "bytes read)\n", current->comm, nbytes);
+
+	return lrng_read_common(buf, nbytes, lrng_sdrng_get_sleep);
+}
+
+static ssize_t lrng_drng_write(struct file *file, const char __user *buffer,
+			       size_t count, loff_t *ppos)
+{
+	return lrng_drng_write_common(buffer, count, 0);
+}
+
+static long lrng_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
+{
+	int size, ent_count_bits;
+	int __user *p = (int __user *)arg;
+
+	switch (cmd) {
+	case RNDGETENTCNT:
+		ent_count_bits = lrng_avail_entropy();
+		if (put_user(ent_count_bits, p))
+			return -EFAULT;
+		return 0;
+	case RNDADDTOENTCNT:
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+		if (get_user(ent_count_bits, p))
+			return -EFAULT;
+		ent_count_bits = (int)lrng_avail_entropy() + ent_count_bits;
+		if (ent_count_bits < 0)
+			ent_count_bits = 0;
+		if (ent_count_bits > LRNG_POOL_SIZE_BITS)
+			ent_count_bits = LRNG_POOL_SIZE_BITS;
+		lrng_pool_set_entropy(ent_count_bits);
+		return 0;
+	case RNDADDENTROPY:
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+		if (get_user(ent_count_bits, p++))
+			return -EFAULT;
+		if (ent_count_bits < 0)
+			return -EINVAL;
+		if (get_user(size, p++))
+			return -EFAULT;
+		if (size < 0)
+			return -EINVAL;
+		/* there cannot be more entropy than data */
+		ent_count_bits = min(ent_count_bits, size<<3);
+		return lrng_drng_write_common((const char __user *)p, size,
+					      ent_count_bits);
+	case RNDZAPENTCNT:
+	case RNDCLEARPOOL:
+		/* Clear the entropy pool counter. */
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+		lrng_pool_set_entropy(0);
+		return 0;
+	case RNDRESEEDCRNG:
+		/*
+		 * We leave the capability check here since it is present
+		 * in the upstream's RNG implementation. Yet, user space
+		 * can trigger a reseed as easy as writing into /dev/random
+		 * or /dev/urandom where no privilege is needed.
+		 */
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+		/* Force a reseed of all secondary DRNGs */
+		lrng_sdrng_force_reseed();
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
+static int lrng_fasync(int fd, struct file *filp, int on)
+{
+	return fasync_helper(fd, filp, on, &fasync);
+}
+
+const struct file_operations random_fops = {
+	.read  = lrng_trng_read,
+	.write = lrng_drng_write,
+	.poll  = lrng_trng_poll,
+	.unlocked_ioctl = lrng_ioctl,
+	.fasync = lrng_fasync,
+	.llseek = noop_llseek,
+};
+
+const struct file_operations urandom_fops = {
+	.read  = lrng_sdrng_read,
+	.write = lrng_drng_write,
+	.unlocked_ioctl = lrng_ioctl,
+	.fasync = lrng_fasync,
+	.llseek = noop_llseek,
+};
+
+SYSCALL_DEFINE3(getrandom, char __user *, buf, size_t, count,
+		unsigned int, flags)
+{
+	if (flags & ~(GRND_NONBLOCK|GRND_RANDOM))
+		return -EINVAL;
+
+	if (count > INT_MAX)
+		count = INT_MAX;
+
+	if (flags & GRND_RANDOM)
+		return lrng_trng_read_common(flags & GRND_NONBLOCK, buf, count);
+
+	if (unlikely(!lrng_state_operational())) {
+		int ret;
+
+		if (flags & GRND_NONBLOCK)
+			return -EAGAIN;
+		ret = wait_event_interruptible(lrng_init_wait,
+					       lrng_state_operational());
+		if (unlikely(ret))
+			return ret;
+	}
+
+	return lrng_sdrng_read(NULL, buf, count, NULL);
+}
diff --git a/drivers/char/lrng/lrng_internal.h b/drivers/char/lrng/lrng_internal.h
new file mode 100644
index 000000000000..242f9b5b4f3d
--- /dev/null
+++ b/drivers/char/lrng/lrng_internal.h
@@ -0,0 +1,313 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
+/*
+ * Copyright (C) 2018 - 2019, Stephan Mueller <smueller@chronox.de>
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#ifndef _LRNG_INTERNAL_H
+#define _LRNG_INTERNAL_H
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+
+/*************************** General LRNG parameter ***************************/
+
+/* Security strength of LRNG -- this must match DRNG security strength */
+#define LRNG_DRNG_SECURITY_STRENGTH_BYTES 32
+#define LRNG_DRNG_SECURITY_STRENGTH_BITS (LRNG_DRNG_SECURITY_STRENGTH_BYTES * 8)
+#define LRNG_DRNG_BLOCKSIZE 64		/* Maximum of DRNG block sizes */
+
+/*
+ * SP800-90A defines a maximum request size of 1<<16 bytes. The given value is
+ * considered a safer margin. This applies to the secondary DRNGs.
+ *
+ * This value is allowed to be changed.
+ */
+#define LRNG_DRNG_MAX_REQSIZE		(1<<12)
+
+/*
+ * SP800-90A defines a maximum number of requests between reseeds of 2^48.
+ * The given value is considered a much safer margin, balancing requests for
+ * frequent reseeds with the need to conserve entropy. This value MUST NOT be
+ * larger than INT_MAX because it is used in an atomic_t. This applies to the
+ * secondary DRNGs.
+ *
+ * This value is allowed to be changed.
+ */
+#define LRNG_DRNG_RESEED_THRESH		(1<<20)
+
+/*
+ * Number of interrupts to be recorded to assume that DRNG security strength
+ * bits of entropy are received.
+ * Note: a value below the DRNG security strength should not be defined as this
+ *	 may imply the DRNG can never be fully seeded in case other noise
+ *	 sources are unavailable.
+ *
+ * This value is allowed to be changed.
+ */
+#define LRNG_IRQ_ENTROPY_BITS		LRNG_DRNG_SECURITY_STRENGTH_BITS
+
+/*
+ * Leave given amount of entropy in bits entropy pool to serve /dev/random while
+ * /dev/urandom is stressed.
+ *
+ * This value is allowed to be changed.
+ */
+#define LRNG_EMERG_ENTROPY		(LRNG_DRNG_SECURITY_STRENGTH_BITS * 2)
+
+/*
+ * Amount of entropy that is lost with the conditioning functions of LFSR and
+ * hash_df as shown with the entropy analysis compliant to SP800-90B.
+ */
+#define LRNG_CONDITIONING_ENTROPY_LOSS	1
+
+/*
+ * Min required seed entropy is 128 bits covering the minimum entropy
+ * requirement of SP800-131A and the German BSI's TR02102.
+ *
+ * This value is allowed to be changed.
+ */
+#define LRNG_FULL_SEED_ENTROPY_BITS	LRNG_DRNG_SECURITY_STRENGTH_BITS
+#define LRNG_MIN_SEED_ENTROPY_BITS	128
+#define LRNG_INIT_ENTROPY_BITS		32
+
+/*
+ * Oversampling factor of IRQ events to obtain
+ * LRNG_DRNG_SECURITY_STRENGTH_BYTES. This factor is used when a
+ * high-resolution time stamp is not available. In this case, jiffies and
+ * register contents are used to fill the entropy pool. These noise sources
+ * are much less entropic than the high-resolution timer. The entropy content
+ * is the entropy content assumed with LRNG_IRQ_ENTROPY_BITS divided by
+ * LRNG_IRQ_OVERSAMPLING_FACTOR.
+ *
+ * This value is allowed to be changed.
+ */
+#define LRNG_IRQ_OVERSAMPLING_FACTOR	10
+
+/*
+ * Alignmask which should cover all cipher implementations
+ * WARNING: If this is changed to a value larger than 8, manual
+ * alignment is necessary as older versions of GCC may not be capable
+ * of aligning stack variables at boundaries greater than 8.
+ * In this case, PTR_ALIGN must be used.
+ */
+#define LRNG_KCAPI_ALIGN		8
+
+/************************ Default DRNG implementation *************************/
+
+extern struct chacha20_state primary_chacha20;
+extern struct chacha20_state secondary_chacha20;
+extern const struct lrng_crypto_cb lrng_cc20_crypto_cb;
+void lrng_cc20_init_state(struct chacha20_state *state);
+
+/********************************** /proc *************************************/
+
+static inline void lrng_pool_inc_numa_node(void) { }
+
+/****************************** LRNG interfaces *******************************/
+
+extern u32 lrng_read_wakeup_bits;
+extern u32 lrng_write_wakeup_bits;
+extern int lrng_sdrng_reseed_max_time;
+
+void lrng_reader_wakeup(void);
+void lrng_writer_wakeup(void);
+void lrng_init_wakeup(void);
+void lrng_debug_report_seedlevel(const char *name);
+void lrng_process_ready_list(void);
+
+/************************** Entropy pool management ***************************/
+
+#define LRNG_POOL_SIZE			(128 << CONFIG_LRNG_POOL_SIZE)
+#define LRNG_POOL_WORD_BYTES		(sizeof(atomic_t))
+#define LRNG_POOL_SIZE_BYTES		(LRNG_POOL_SIZE * LRNG_POOL_WORD_BYTES)
+#define LRNG_POOL_SIZE_BITS		(LRNG_POOL_SIZE_BYTES * 8)
+#define LRNG_POOL_WORD_BITS		(LRNG_POOL_WORD_BYTES * 8)
+
+void lrng_state_init_seed_work(void);
+u32 lrng_avail_entropy(void);
+void lrng_set_entropy_thresh(u32 new);
+int lrng_pool_trylock(void);
+void lrng_pool_unlock(void);
+void lrng_reset_state(void);
+void lrng_pool_all_numa_nodes_seeded(void);
+bool lrng_state_min_seeded(void);
+bool lrng_state_fully_seeded(void);
+bool lrng_state_operational(void);
+bool lrng_pool_highres_timer(void);
+void lrng_pool_set_entropy(u32 entropy_bits);
+void lrng_pool_configure(bool highres_timer, u32 irq_entropy_bits);
+void lrng_pool_lfsr(const u8 *buf, u32 buflen);
+void lrng_pool_lfsr_nonaligned(const u8 *buf, u32 buflen);
+void lrng_pool_lfsr_u32(u32 value);
+void lrng_pool_add_irq(u32 irq_num);
+void lrng_pool_add_entropy(u32 entropy_bits);
+
+struct entropy_buf {
+	u8 a[LRNG_DRNG_SECURITY_STRENGTH_BYTES];
+	u8 b[LRNG_DRNG_SECURITY_STRENGTH_BYTES];
+	u8 c[LRNG_DRNG_SECURITY_STRENGTH_BYTES];
+	u32 now;
+};
+
+int lrng_fill_seed_buffer(const struct lrng_crypto_cb *crypto_cb,
+			  void *hash, struct entropy_buf *entropy_buf,
+			  bool drain);
+void lrng_init_ops(u32 seed_bits);
+
+/************************** Jitter RNG Noise Source ***************************/
+
+#ifdef CONFIG_LRNG_JENT
+u32 lrng_get_jent(u8 *outbuf, unsigned int outbuflen);
+u32 lrng_jent_entropylevel(void);
+#else /* CONFIG_CRYPTO_JITTERENTROPY */
+static inline u32 lrng_get_jent(u8 *outbuf, unsigned int outbuflen) {return 0; }
+static inline u32 lrng_jent_entropylevel(void) { return 0; }
+#endif /* CONFIG_CRYPTO_JITTERENTROPY */
+
+/*************************** CPU-based Noise Source ***************************/
+
+u32 lrng_get_arch(u8 *outbuf);
+u32 lrng_slow_noise_req_entropy(u32 required_entropy_bits);
+
+/****************** True Random Number Generator processing *******************/
+
+#ifdef CONFIG_LRNG_TRNG_SUPPORT
+
+void lrng_trng_reset(void);
+void lrng_trng_init(void);
+int lrng_trng_get(u8 *outbuf, u32 outbuflen);
+int lrng_trng_seed(u8 *outbuf, u32 outbuflen, bool fullentropy, bool drain);
+# ifdef CONFIG_LRNG_DRNG_SWITCH
+int lrng_trng_switch(const struct lrng_crypto_cb *cb);
+# endif
+
+#else	/* CONFIG_LRNG_TRNG_SUPPORT */
+
+static inline void lrng_trng_reset(void) {}
+static inline void lrng_trng_init(void) {}
+#define lrng_trng_get lrng_sdrng_get_sleep
+
+# ifdef CONFIG_LRNG_DRNG_SWITCH
+static inline int lrng_trng_switch(const struct lrng_crypto_cb *cb) {return 0; }
+# endif
+
+#endif	/* CONFIG_LRNG_TRNG_SUPPORT */
+
+/************************* secondary DRNG processing **************************/
+
+/* Secondary DRNG state handle */
+struct lrng_sdrng {
+	void *sdrng;				/* DRNG handle */
+	void *hash;				/* Hash handle */
+	const struct lrng_crypto_cb *crypto_cb;	/* Crypto callbacks */
+	atomic_t requests;			/* Number of DRNG requests */
+	unsigned long last_seeded;		/* Last time it was seeded */
+	bool fully_seeded;			/* Is DRNG fully seeded? */
+	bool force_reseed;			/* Force a reseed */
+	struct mutex lock;
+	spinlock_t spin_lock;
+};
+
+extern struct mutex lrng_crypto_cb_update;
+
+struct lrng_sdrng *lrng_sdrng_init_instance(void);
+struct lrng_sdrng *lrng_sdrng_atomic_instance(void);
+
+static __always_inline bool lrng_sdrng_is_atomic(struct lrng_sdrng *sdrng)
+{
+	return (sdrng->sdrng == lrng_sdrng_atomic_instance()->sdrng);
+}
+
+/* Lock the secondary DRNG */
+static __always_inline void lrng_sdrng_lock(struct lrng_sdrng *sdrng,
+					    unsigned long *flags)
+{
+	/* Use spin lock in case the atomic DRNG context is used */
+	if (lrng_sdrng_is_atomic(sdrng))
+		spin_lock_irqsave(&sdrng->spin_lock, *flags);
+	else
+		mutex_lock(&sdrng->lock);
+}
+
+/* Unlock the secondary DRNG */
+static __always_inline void lrng_sdrng_unlock(struct lrng_sdrng *sdrng,
+					      unsigned long *flags)
+{
+	if (lrng_sdrng_is_atomic(sdrng))
+		spin_unlock_irqrestore(&sdrng->spin_lock, *flags);
+	else
+		mutex_unlock(&sdrng->lock);
+}
+
+bool lrng_get_available(void);
+void lrng_set_available(void);
+void lrng_drngs_init_cc20(void);
+void lrng_sdrng_reset(struct lrng_sdrng *sdrng);
+int lrng_sdrng_get_atomic(u8 *outbuf, u32 outbuflen);
+int lrng_sdrng_get_sleep(u8 *outbuf, u32 outbuflen);
+void lrng_sdrng_force_reseed(void);
+void lrng_sdrng_seed_work(struct work_struct *dummy);
+
+static inline struct lrng_sdrng **lrng_sdrng_instances(void) { return NULL; }
+static inline void lrng_drngs_numa_alloc(void) { return; }
+
+/************************** Health Test linking code **************************/
+
+enum lrng_health_res {
+	lrng_health_pass,		/* Health test passes on time stamp */
+	lrng_health_fail_use,		/* Time stamp unhealthy, but mix in */
+	lrng_health_fail_drop		/* Time stamp unhealthy, drop it */
+};
+
+#ifdef CONFIG_LRNG_HEALTH_TESTS
+bool lrng_sp80090b_startup_complete(void);
+bool lrng_sp80090b_compliant(void);
+
+enum lrng_health_res lrng_health_test(u32 now_time);
+void lrng_health_disable(void);
+
+void lrng_reset(void);
+#else	/* CONFIG_LRNG_HEALTH_TESTS */
+static inline bool lrng_sp80090b_startup_complete(void) { return true; }
+static inline bool lrng_sp80090b_compliant(void) { return false; }
+
+static inline enum lrng_health_res
+lrng_health_test(u32 now_time) { return lrng_health_pass; }
+static inline void lrng_health_disable(void) { }
+#endif	/* CONFIG_LRNG_HEALTH_TESTS */
+
+/****************************** Helper code ***********************************/
+
+static inline u32 atomic_read_u32(atomic_t *v)
+{
+	return (u32)atomic_read(v);
+}
+
+/*************************** Auxiliary functions ******************************/
+
+void invalidate_batched_entropy(void);
+
+/***************************** Testing code ***********************************/
+
+#ifdef CONFIG_LRNG_TESTING
+bool lrng_raw_entropy_store(u32 value);
+#else	/* CONFIG_LRNG_TESTING */
+static inline bool lrng_raw_entropy_store(u32 value) { return false; }
+#endif	/* CONFIG_LRNG_TESTING */
+
+#endif /* _LRNG_INTERNAL_H */
diff --git a/drivers/char/lrng/lrng_pool.c b/drivers/char/lrng/lrng_pool.c
new file mode 100644
index 000000000000..61a03206cf67
--- /dev/null
+++ b/drivers/char/lrng/lrng_pool.c
@@ -0,0 +1,673 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG Entropy pool management
+ *
+ * Copyright (C) 2016 - 2019, Stephan Mueller <smueller@chronox.de>
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <asm/irq_regs.h>
+#include <linux/lrng.h>
+#include <linux/percpu.h>
+#include <linux/random.h>
+#include <linux/utsname.h>
+#include <linux/workqueue.h>
+
+#include "lrng_internal.h"
+
+struct lrng_state {
+	bool lrng_operational;			/* Is DRNG operational? */
+	bool lrng_fully_seeded;			/* Is DRNG fully seeded? */
+	bool lrng_min_seeded;			/* Is DRNG minimally seeded? */
+	struct work_struct lrng_seed_work;	/* (re)seed work queue */
+};
+
+/* Status information about IRQ noise source */
+struct lrng_irq_info {
+	atomic_t num_events;	/* Number of healthy IRQs since last read */
+	atomic_t num_events_thresh;	/* Reseed threshold */
+	atomic_t reseed_in_progress;	/* Flag for on executing reseed */
+	bool irq_highres_timer;	/* Is high-resolution timer available? */
+	u32 irq_entropy_bits;	/* LRNG_IRQ_ENTROPY_BITS? */
+};
+
+/*
+ * This is the entropy pool used by the slow noise source. Its size should
+ * be at least as large as LRNG_DRNG_SECURITY_STRENGTH_BITS.
+ *
+ * The pool array is aligned to 8 bytes to comfort the kernel crypto API cipher
+ * implementations of the hash functions used to read the pool: for some
+ * accelerated implementations, we need an alignment to avoid a realignment
+ * which involves memcpy(). The alignment to 8 bytes should satisfy all crypto
+ * implementations.
+ *
+ * LRNG_POOL_SIZE is allowed to be changed only if the taps of the polynomial
+ * used for the LFSR are changed as well. The size must be in powers of 2 due
+ * to the mask handling in lrng_pool_lfsr_u32 which uses AND instead of modulo.
+ */
+struct lrng_pool {
+	union {
+		struct {
+			/*
+			 * hash_df implementation: counter, requested_bits and
+			 * pool form a linear buffer that is used in the
+			 * hash_df function specified in SP800-90A section
+			 * 10.3.1
+			 */
+			unsigned char counter;
+			__be32 requested_bits;
+
+			/* Pool */
+			atomic_t pool[LRNG_POOL_SIZE];
+			/* Ptr into pool for next IRQ word injection */
+			atomic_t pool_ptr;
+			/* rotate for LFSR */
+			atomic_t input_rotate;
+			/* All NUMA DRNGs seeded? */
+			bool all_online_numa_node_seeded;
+			/* IRQ noise source status info */
+			struct lrng_irq_info irq_info;
+			/* Serialize read of entropy pool */
+			spinlock_t lock;
+		};
+		/*
+		 * Static SHA-1 implementation in lrng_cc20_hash_buffer
+		 * processes data 64-byte-wise. Hence, ensure proper size
+		 * of LRNG entropy pool data structure.
+		 */
+		u8 hash_input_buf[LRNG_POOL_SIZE_BYTES + 64];
+	};
+};
+
+static struct lrng_pool lrng_pool __aligned(LRNG_KCAPI_ALIGN) = {
+	.irq_info	= {
+		.irq_entropy_bits	= LRNG_IRQ_ENTROPY_BITS,
+		.num_events_thresh	= ATOMIC_INIT(LRNG_INIT_ENTROPY_BITS +
+						LRNG_CONDITIONING_ENTROPY_LOSS),
+		/* Sample IRQ pointer data at least during boot */
+		.irq_highres_timer	= false },
+	.lock		= __SPIN_LOCK_UNLOCKED(lrng_pool.lock)
+};
+
+static struct lrng_state lrng_state = { false, false, false, };
+
+/********************************** Helper ***********************************/
+
+void lrng_state_init_seed_work(void)
+{
+	INIT_WORK(&lrng_state.lrng_seed_work, lrng_sdrng_seed_work);
+}
+
+static inline u32 lrng_entropy_to_data(u32 entropy_bits)
+{
+	return ((entropy_bits * lrng_pool.irq_info.irq_entropy_bits) /
+		LRNG_DRNG_SECURITY_STRENGTH_BITS);
+}
+
+static inline u32 lrng_data_to_entropy(u32 irqnum)
+{
+	return ((irqnum * LRNG_DRNG_SECURITY_STRENGTH_BITS) /
+		lrng_pool.irq_info.irq_entropy_bits);
+}
+
+u32 lrng_avail_entropy(void)
+{
+	return min_t(u32, LRNG_POOL_SIZE_BITS, lrng_data_to_entropy(
+			atomic_read_u32(&lrng_pool.irq_info.num_events)));
+}
+
+void lrng_set_entropy_thresh(u32 new)
+{
+	atomic_set(&lrng_pool.irq_info.num_events_thresh,
+		   lrng_entropy_to_data(new));
+}
+
+/*
+ * Reading of the LRNG pool is only allowed by one caller. The reading is
+ * only performed to (re)seed the TRNG or SDRNGs. Thus, if this "lock" is
+ * already taken, the reseeding operation is in progress. The caller is not
+ * intended to wait but continue with its other operation.
+ */
+int lrng_pool_trylock(void)
+{
+	return atomic_cmpxchg(&lrng_pool.irq_info.reseed_in_progress, 0, 1);
+}
+
+void lrng_pool_unlock(void)
+{
+	atomic_set(&lrng_pool.irq_info.reseed_in_progress, 0);
+}
+
+void lrng_reset_state(void)
+{
+	struct lrng_irq_info *irq_info = &lrng_pool.irq_info;
+
+	atomic_set(&irq_info->num_events, 0);
+	lrng_state.lrng_operational = false;
+	lrng_state.lrng_fully_seeded = false;
+	lrng_state.lrng_min_seeded = false;
+	pr_debug("reset LRNG\n");
+}
+
+void lrng_pool_all_numa_nodes_seeded(void)
+{
+	lrng_pool.all_online_numa_node_seeded = true;
+}
+
+bool lrng_state_min_seeded(void)
+{
+	return lrng_state.lrng_min_seeded;
+}
+
+bool lrng_state_fully_seeded(void)
+{
+	return lrng_state.lrng_fully_seeded;
+}
+
+bool lrng_state_operational(void)
+{
+	return lrng_state.lrng_operational;
+}
+
+bool lrng_pool_highres_timer(void)
+{
+	return lrng_pool.irq_info.irq_highres_timer;
+}
+
+void lrng_pool_set_entropy(u32 entropy_bits)
+{
+	atomic_set(&lrng_pool.irq_info.num_events,
+		   lrng_entropy_to_data(entropy_bits));
+}
+
+void lrng_pool_configure(bool highres_timer, u32 irq_entropy_bits)
+{
+	struct lrng_irq_info *irq_info = &lrng_pool.irq_info;
+
+	irq_info->irq_highres_timer = highres_timer;
+	if (irq_info->irq_entropy_bits != irq_entropy_bits) {
+		irq_info->irq_entropy_bits = irq_entropy_bits;
+		/* Reset the threshold based on new oversampling factor. */
+		lrng_set_entropy_thresh(atomic_read_u32(
+						&irq_info->num_events_thresh));
+	}
+}
+
+/* invoke function with buffer aligned to 4 bytes */
+void lrng_pool_lfsr(const u8 *buf, u32 buflen)
+{
+	u32 *p_buf = (u32 *)buf;
+
+	for (; buflen >= 4; buflen -= 4)
+		lrng_pool_lfsr_u32(*p_buf++);
+
+	buf = (u8 *)p_buf;
+	while (buflen--)
+		lrng_pool_lfsr_u32(*buf++);
+}
+
+void lrng_pool_lfsr_nonaligned(const u8 *buf, u32 buflen)
+{
+	while (buflen) {
+		if (!((unsigned long)buf & (sizeof(u32) - 1))) {
+			lrng_pool_lfsr(buf, buflen);
+			return;
+		}
+
+		lrng_pool_lfsr_u32(*buf++);
+		buflen--;
+	}
+}
+
+/**************************** Interrupt processing ****************************/
+
+/*
+ * Implement a (modified) twisted Generalized Feedback Shift Register. (See M.
+ * Matsumoto & Y. Kurita, 1992.  Twisted GFSR generators. ACM Transactions on
+ * Modeling and Computer Simulation 2(3):179-194.  Also see M. Matsumoto & Y.
+ * Kurita, 1994.  Twisted GFSR generators II.  ACM Transactions on Modeling and
+ * Computer Simulation 4:254-266).
+ */
+static u32 const lrng_twist_table[8] = {
+	0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158,
+	0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 };
+
+/*
+ * The polynomials for the LFSR are taken from the document "Table of Linear
+ * Feedback Shift Registers" by Roy Ward, Tim Molteno, October 26, 2007.
+ * The first polynomial is from "Primitive Binary Polynomials" by Wayne
+ * Stahnke (1973) and is primitive as well as irreducible.
+ *
+ * Note, the tap values are smaller by one compared to the documentation because
+ * they are used as an index into an array where the index starts by zero.
+ *
+ * All polynomials were also checked to be primitive and irreducible with magma
+ * which ensures that the key property of the LFSR providing a compression
+ * function for entropy is guaranteed.
+ */
+static u32 const lrng_lfsr_polynomial[][4] = {
+	{ 127, 28, 26, 1 },			/* 128 words by Stahnke */
+	{ 255, 253, 250, 245 },			/* 256 words */
+	{ 511, 509, 506, 503 },			/* 512 words */
+	{ 1023, 1014, 1001, 1000 },		/* 1024 words */
+	{ 2047, 2034, 2033, 2028 },		/* 2048 words */
+	{ 4095, 4094, 4080, 4068 },		/* 4096 words */
+};
+
+/**
+ * Hot code path - inject data into entropy pool using LFSR
+ */
+void lrng_pool_lfsr_u32(u32 value)
+{
+	/*
+	 * Process the LFSR by altering not adjacent words but rather
+	 * more spaced apart words. Using a prime number ensures that all words
+	 * are processed evenly. As some the LFSR polynomials taps are close
+	 * together, processing adjacent words with the LSFR taps may be
+	 * inappropriate as the data just mixed-in at these taps may be not
+	 * independent from the current data to be mixed in.
+	 */
+	u32 ptr = (u32)atomic_add_return_relaxed(67, &lrng_pool.pool_ptr) &
+							(LRNG_POOL_SIZE - 1);
+	/*
+	 * Add 7 bits of rotation to the pool. At the beginning of the
+	 * pool, add an extra 7 bits rotation, so that successive passes
+	 * spread the input bits across the pool evenly.
+	 *
+	 * Note, there is a race between getting ptr and calculating
+	 * input_rotate when ptr is is obtained on two or more CPUs at the
+	 * same time. This race is irrelevant as it may only come into effect
+	 * if 3 or more CPUs race at the same time which is very unlikely. If
+	 * the race happens, it applies to one event only. As this rolling
+	 * supports the LFSR without being strictly needed, we accept this
+	 * race.
+	 */
+	u32 input_rotate = (u32)atomic_add_return_relaxed((ptr ? 7 : 14),
+					&lrng_pool.input_rotate) & 31;
+	u32 word = rol32(value, input_rotate);
+
+	BUILD_BUG_ON(LRNG_POOL_SIZE - 1 !=
+		     lrng_lfsr_polynomial[CONFIG_LRNG_POOL_SIZE][0]);
+	word ^= atomic_read_u32(&lrng_pool.pool[ptr]);
+	word ^= atomic_read_u32(&lrng_pool.pool[
+		(ptr + lrng_lfsr_polynomial[CONFIG_LRNG_POOL_SIZE][0]) &
+		       (LRNG_POOL_SIZE - 1)]);
+	word ^= atomic_read_u32(&lrng_pool.pool[
+		(ptr + lrng_lfsr_polynomial[CONFIG_LRNG_POOL_SIZE][1]) &
+		       (LRNG_POOL_SIZE - 1)]);
+	word ^= atomic_read_u32(&lrng_pool.pool[
+		(ptr + lrng_lfsr_polynomial[CONFIG_LRNG_POOL_SIZE][2]) &
+		       (LRNG_POOL_SIZE - 1)]);
+	word ^= atomic_read_u32(&lrng_pool.pool[
+		(ptr + lrng_lfsr_polynomial[CONFIG_LRNG_POOL_SIZE][3]) &
+		       (LRNG_POOL_SIZE - 1)]);
+
+	word = (word >> 3) ^ lrng_twist_table[word & 7];
+	atomic_set(&lrng_pool.pool[ptr], word);
+}
+
+/**
+ * Hot code path - mix data into entropy pool
+ */
+void lrng_pool_add_irq(u32 irq_num)
+{
+	struct lrng_irq_info *irq_info = &lrng_pool.irq_info;
+
+	atomic_add(irq_num, &irq_info->num_events);
+
+	/* Wake sleeping readers */
+	lrng_reader_wakeup();
+
+	/*
+	 * Once all secondary DRNGs are fully seeded, the interrupt noise
+	 * sources will not trigger any reseeding any more.
+	 */
+	if (likely(lrng_pool.all_online_numa_node_seeded))
+		return;
+
+	/* Only try to reseed if the DRNG is alive. */
+	if (!lrng_get_available())
+		return;
+
+	/* Only trigger the DRNG reseed if we have collected enough IRQs. */
+	if (atomic_read_u32(&lrng_pool.irq_info.num_events) <
+	    atomic_read_u32(&lrng_pool.irq_info.num_events_thresh))
+		return;
+
+	/* Ensure that the seeding only occurs once at any given time. */
+	if (lrng_pool_trylock())
+		return;
+
+	/* Seed the DRNG with IRQ noise. */
+	schedule_work(&lrng_state.lrng_seed_work);
+}
+
+void lrng_pool_add_entropy(u32 entropy_bits)
+{
+	lrng_pool_add_irq(lrng_entropy_to_data(entropy_bits));
+}
+
+/**
+ * Generate a hashed output of pool using the SP800-90A section 10.3.1 hash_df
+ * function
+ */
+static inline u32 lrng_pool_hash_df(const struct lrng_crypto_cb *crypto_cb,
+				    void *hash, u8 *outbuf, u32 requested_bits)
+{
+	struct lrng_pool *pool = &lrng_pool;
+	u32 digestsize, requested_bytes = requested_bits >> 3,
+	    generated_bytes = 0;
+	u8 digest[64] __aligned(LRNG_KCAPI_ALIGN);
+
+	digestsize = crypto_cb->lrng_hash_digestsize(hash);
+	if (digestsize > sizeof(digest)) {
+		pr_err("Digest buffer too small\n");
+		return 0;
+	}
+
+	pool->counter = 1;
+	pool->requested_bits = cpu_to_be32(requested_bytes << 3);
+
+	while (requested_bytes) {
+		u32 tocopy = min_t(u32, requested_bytes, digestsize);
+
+		/* The counter must not wrap */
+		if (pool->counter == 0)
+			goto out;
+
+		if (crypto_cb->lrng_hash_buffer(hash, (u8 *)pool,
+						LRNG_POOL_SIZE_BYTES + 64,
+						digest))
+			goto out;
+
+		/* Copy the data out to the caller */
+		memcpy(outbuf + generated_bytes, digest, tocopy);
+		requested_bytes -= tocopy;
+		generated_bytes += tocopy;
+		pool->counter++;
+	}
+
+out:
+	/* Mix read data back into pool for backtracking resistance */
+	if (generated_bytes)
+		lrng_pool_lfsr(outbuf, generated_bytes);
+	memzero_explicit(digest, digestsize);
+	return (generated_bytes<<3);
+}
+
+/**
+ * Read the entropy pool out for use.
+ *
+ * This function handles the translation from the number of received interrupts
+ * into an entropy statement. The conversion depends on LRNG_IRQ_ENTROPY_BITS
+ * which defines how many interrupts must be received to obtain 256 bits of
+ * entropy. With this value, the function lrng_data_to_entropy converts a given
+ * data size (received interrupts, requested amount of data, etc.) into an
+ * entropy statement. lrng_entropy_to_data does the reverse.
+ *
+ * Both functions are agnostic about the type of data: when the number of
+ * interrupts is processed by these functions, the resulting entropy value is in
+ * bits as we assume the entropy of interrupts is measured in bits. When data is
+ * processed, the entropy value is in bytes as the data is measured in bytes.
+ *
+ * @outbuf: buffer to store data in with size LRNG_DRNG_SECURITY_STRENGTH_BYTES
+ * @requested_entropy_bits: requested bits of entropy -- the function will
+ *			    return at least this amount of entropy if available
+ * @drain: boolean indicating that that all entropy of pool can be used
+ *	   (otherwise some emergency amount of entropy is left)
+ * @return: estimated entropy from the IRQs that was obtained
+ */
+static u32 lrng_get_pool(const struct lrng_crypto_cb *crypto_cb, void *hash,
+			 u8 *outbuf, u32 requested_entropy_bits, bool drain)
+{
+	struct lrng_pool *pool = &lrng_pool;
+	unsigned long flags;
+	u32 irq_num_events_used, irq_num_events, avail_entropy_bits;
+
+	/* This get_pool operation must only be called once at a given time! */
+	spin_lock_irqsave(&pool->lock, flags);
+
+	/* How many unused interrupts are in entropy pool? */
+	irq_num_events = atomic_read_u32(&lrng_pool.irq_info.num_events);
+	/* Convert available interrupts into entropy statement */
+	avail_entropy_bits = lrng_data_to_entropy(irq_num_events);
+
+	/* Cap available entropy to pool size */
+	avail_entropy_bits =
+			min_t(u32, avail_entropy_bits, LRNG_POOL_SIZE_BITS);
+
+	/* How much entropy we need to and can we use? */
+	if (drain) {
+		struct lrng_state *state = &lrng_state;
+
+		/* read for the TRNG or not fully seeded 2ndary DRNG */
+		if (!state->lrng_fully_seeded) {
+			/*
+			 * During boot time, we read 256 bits data with
+			 * avail_entropy_bits entropy. In case our conservative
+			 * entropy estimate underestimates the available entropy
+			 * we can transport as much available entropy as
+			 * possible. The primary DRNG is no TRNG yet.
+			 */
+			requested_entropy_bits =
+					LRNG_DRNG_SECURITY_STRENGTH_BITS;
+		} else {
+			requested_entropy_bits = min_t(u32, avail_entropy_bits,
+						       requested_entropy_bits);
+		}
+	} else {
+		/*
+		 * Read for 2ndary DRNG: leave the emergency fill level.
+		 *
+		 * Only obtain data if we have at least the requested entropy
+		 * available. The idea is to prevent the transfer of, say
+		 * one byte at a time, because one byte of entropic data
+		 * can be brute forced by an attacker.
+		 */
+		if ((requested_entropy_bits + LRNG_EMERG_ENTROPY) >
+		     avail_entropy_bits) {
+			requested_entropy_bits = 0;
+			goto out;
+		}
+	}
+
+	/* Hash is a compression function: we generate entropy amount of data */
+	requested_entropy_bits = round_down(requested_entropy_bits, 8);
+
+	requested_entropy_bits = lrng_pool_hash_df(crypto_cb, hash, outbuf,
+						   requested_entropy_bits);
+
+	/* Boot time: After getting the full buffer adjust the entropy value. */
+	requested_entropy_bits = min_t(u32, avail_entropy_bits,
+				       requested_entropy_bits);
+
+out:
+	/* Convert used entropy into interrupt number for subtraction */
+	irq_num_events_used = lrng_entropy_to_data(requested_entropy_bits);
+
+	/*
+	 * The hash_df operation entropy assessment shows that the output
+	 * entropy is one bit smaller than the input entropy. Therefore we
+	 * account for this one bit of entropy here: if we have sufficient
+	 * entropy in the LFSR, we say we used one bit of entropy more.
+	 * Otherwise we reduce the amount of entropy we say we generated with
+	 * the hash_df.
+	 */
+	if ((irq_num_events_used + LRNG_CONDITIONING_ENTROPY_LOSS) <=
+	    lrng_entropy_to_data(avail_entropy_bits)) {
+		irq_num_events_used += LRNG_CONDITIONING_ENTROPY_LOSS;
+	} else {
+		if (unlikely(requested_entropy_bits <
+			     LRNG_CONDITIONING_ENTROPY_LOSS))
+			requested_entropy_bits = 0;
+		else
+			requested_entropy_bits -=
+						LRNG_CONDITIONING_ENTROPY_LOSS;
+	}
+
+	/*
+	 * New events might have arrived in the meanwhile and we don't
+	 * want to throw them away unconditionally. On the other hand,
+	 * these new events might have been mixed in before
+	 * lrng_hash_df_pool() had been able to draw any entropy
+	 * from the pool and thus, the pool capacity might have been
+	 * exceeded at some point. Note that in theory, some events
+	 * might get lost inbetween the atomic_read() and
+	 * atomic_set() below. But that's fine, because it's no real
+	 * concern while code preventing this would come at the cost of
+	 * additional complexity. Likewise, some events which arrived
+	 * after full or partial completion of the __lrng_hash_df_pool()
+	 * above might get unnecessarily thrown away by the min()
+	 * operation below; the same argument applies there.
+	 */
+	irq_num_events = atomic_read_u32(&lrng_pool.irq_info.num_events);
+	irq_num_events = min_t(u32, irq_num_events,
+			       lrng_entropy_to_data(LRNG_POOL_SIZE_BITS));
+	irq_num_events -= irq_num_events_used;
+	atomic_set(&lrng_pool.irq_info.num_events, irq_num_events);
+
+	spin_unlock_irqrestore(&pool->lock, flags);
+
+	/* Obtain entropy statement in bits from the used entropy */
+	pr_debug("obtained %u bits of entropy from %u newly collected "
+		 "interrupts - not using %u interrupts\n",
+		 requested_entropy_bits, irq_num_events_used,
+		 irq_num_events);
+
+	return requested_entropy_bits;
+}
+
+/* Fill the seed buffer with data from the noise sources */
+int lrng_fill_seed_buffer(const struct lrng_crypto_cb *crypto_cb, void *hash,
+			  struct entropy_buf *entropy_buf, bool drain)
+{
+	struct lrng_state *state = &lrng_state;
+	u32 total_entropy_bits = 0;
+
+	/* Require at least 128 bits of entropy for any reseed. */
+	if (state->lrng_fully_seeded &&
+	    lrng_avail_entropy() <
+	    lrng_slow_noise_req_entropy(lrng_read_wakeup_bits))
+		goto wakeup;
+
+	/* Drain the pool completely during init and when /dev/random calls. */
+	total_entropy_bits = lrng_get_pool(crypto_cb, hash, entropy_buf->a,
+					   LRNG_DRNG_SECURITY_STRENGTH_BITS,
+					   drain);
+
+	/*
+	 * Concatenate the output of the noise sources. This would be the
+	 * spot to add an entropy extractor logic if desired. Note, this
+	 * has the ability to collect entropy equal or larger than the DRNG
+	 * strength to be able to feed /dev/random.
+	 */
+	total_entropy_bits += lrng_get_arch(entropy_buf->b);
+	total_entropy_bits += lrng_get_jent(entropy_buf->c,
+					    LRNG_DRNG_SECURITY_STRENGTH_BYTES);
+
+	/* also reseed the DRNG with the current time stamp */
+	entropy_buf->now = random_get_entropy();
+
+wakeup:
+	/*
+	 * Shall we wake up user space writers? This location covers
+	 * /dev/urandom as well, but also ensures that the user space provider
+	 * does not dominate the internal noise sources since in case the
+	 * first call of this function finds sufficient entropy in the TRNG, it
+	 * will not trigger the wakeup. This implies that when the next
+	 * /dev/urandom read happens, the TRNG is drained and the internal
+	 * noise sources are asked to feed the TRNG.
+	 */
+	lrng_writer_wakeup();
+
+	return total_entropy_bits;
+}
+
+/**
+ * Set the slow noise source reseed trigger threshold. The initial threshold
+ * is set to the minimum data size that can be read from the pool: a word. Upon
+ * reaching this value, the next seed threshold of 128 bits is set followed
+ * by 256 bits.
+ *
+ * @entropy_bits: size of entropy currently injected into DRNG
+ */
+void lrng_init_ops(u32 seed_bits)
+{
+	struct lrng_state *state = &lrng_state;
+
+	if (state->lrng_operational)
+		return;
+
+	/* DRNG is seeded with full security strength */
+	if (state->lrng_fully_seeded) {
+		state->lrng_operational = lrng_sp80090b_startup_complete();
+		lrng_init_wakeup();
+	} else if (seed_bits >= LRNG_FULL_SEED_ENTROPY_BITS) {
+		invalidate_batched_entropy();
+		state->lrng_fully_seeded = true;
+		state->lrng_operational = lrng_sp80090b_startup_complete();
+		state->lrng_min_seeded = true;
+		pr_info("LRNG fully seeded with %u bits of entropy\n",
+			seed_bits);
+		lrng_set_entropy_thresh(LRNG_FULL_SEED_ENTROPY_BITS +
+					LRNG_CONDITIONING_ENTROPY_LOSS);
+		lrng_process_ready_list();
+		lrng_init_wakeup();
+
+	} else if (!state->lrng_min_seeded) {
+
+		/* DRNG is seeded with at least 128 bits of entropy */
+		if (seed_bits >= LRNG_MIN_SEED_ENTROPY_BITS) {
+			invalidate_batched_entropy();
+			state->lrng_min_seeded = true;
+			pr_info("LRNG minimally seeded with %u bits of "
+				"entropy\n", seed_bits);
+			lrng_set_entropy_thresh(
+				lrng_slow_noise_req_entropy(
+					LRNG_FULL_SEED_ENTROPY_BITS +
+					LRNG_CONDITIONING_ENTROPY_LOSS));
+			lrng_process_ready_list();
+			lrng_init_wakeup();
+
+		/* DRNG is seeded with at least LRNG_INIT_ENTROPY_BITS bits */
+		} else if (seed_bits >= LRNG_INIT_ENTROPY_BITS) {
+			pr_info("LRNG initial entropy level %u bits of "
+				"entropy\n", seed_bits);
+			lrng_set_entropy_thresh(
+				lrng_slow_noise_req_entropy(
+					LRNG_MIN_SEED_ENTROPY_BITS +
+					LRNG_CONDITIONING_ENTROPY_LOSS));
+		}
+	}
+}
+
+int __init rand_initialize(void)
+{
+	ktime_t now_time = ktime_get_real();
+	unsigned int i, rand;
+
+	lrng_pool_lfsr_u32(now_time);
+	for (i = 0; i < LRNG_POOL_SIZE; i++) {
+		if (!arch_get_random_seed_int(&rand) &&
+		    !arch_get_random_int(&rand))
+			rand = random_get_entropy();
+		lrng_pool_lfsr_u32(rand);
+	}
+	lrng_pool_lfsr_nonaligned((u8 *)utsname(), sizeof(*(utsname())));
+
+	return 0;
+}
diff --git a/drivers/char/lrng/lrng_sdrng.c b/drivers/char/lrng/lrng_sdrng.c
new file mode 100644
index 000000000000..570e9b34ddfd
--- /dev/null
+++ b/drivers/char/lrng/lrng_sdrng.c
@@ -0,0 +1,458 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG secondary DRNG processing
+ *
+ * Copyright (C) 2016 - 2019, Stephan Mueller <smueller@chronox.de>
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/lrng.h>
+
+#include "lrng_internal.h"
+
+/*
+ * Maximum number of seconds between DRNG reseed intervals of the secondary
+ * DRNG. Note, this is enforced with the next request of random numbers from
+ * the secondary DRNG. Setting this value to zero implies a reseeding attempt
+ * before every generated random number.
+ */
+int lrng_sdrng_reseed_max_time = 600;
+
+static atomic_t lrng_avail = ATOMIC_INIT(0);
+
+DEFINE_MUTEX(lrng_crypto_cb_update);
+
+/* Secondary DRNG for /dev/urandom, getrandom(2), get_random_bytes */
+static struct lrng_sdrng lrng_sdrng_init = {
+	.sdrng		= &secondary_chacha20,
+	.crypto_cb	= &lrng_cc20_crypto_cb,
+	.lock		= __MUTEX_INITIALIZER(lrng_sdrng_init.lock),
+	.spin_lock	= __SPIN_LOCK_UNLOCKED(lrng_sdrng_init.spin_lock)
+};
+
+/*
+ * Secondary DRNG for get_random_bytes when called in atomic context. This
+ * DRNG will always use the ChaCha20 DRNG. It will never benefit from a
+ * DRNG switch like the "regular" secondary DRNG. If there was no DRNG
+ * switch, the atomic secondary DRNG is identical to the "regular" secondary
+ * DRNG.
+ *
+ * The reason for having this is due to the fact that DRNGs other than
+ * the ChaCha20 DRNG may sleep.
+ */
+static struct lrng_sdrng lrng_sdrng_atomic = {
+	.sdrng		= &secondary_chacha20,
+	.crypto_cb	= &lrng_cc20_crypto_cb,
+	.spin_lock	= __SPIN_LOCK_UNLOCKED(lrng_sdrng_atomic.spin_lock)
+};
+
+/********************************** Helper ************************************/
+
+bool lrng_get_available(void)
+{
+	return likely(atomic_read(&lrng_avail));
+}
+
+void lrng_set_available(void)
+{
+	atomic_set(&lrng_avail, 1);
+}
+
+struct lrng_sdrng *lrng_sdrng_init_instance(void)
+{
+	return &lrng_sdrng_init;
+}
+
+struct lrng_sdrng *lrng_sdrng_atomic_instance(void)
+{
+	return &lrng_sdrng_atomic;
+}
+
+void lrng_sdrng_reset(struct lrng_sdrng *sdrng)
+{
+	atomic_set(&sdrng->requests, LRNG_DRNG_RESEED_THRESH);
+	sdrng->last_seeded = jiffies;
+	sdrng->fully_seeded = false;
+	sdrng->force_reseed = true;
+	pr_debug("reset secondary DRNG\n");
+}
+
+/************************* Random Number Generation ***************************/
+
+/* Inject a data buffer into the secondary DRNG */
+static void lrng_sdrng_inject(struct lrng_sdrng *sdrng,
+			      const u8 *inbuf, u32 inbuflen)
+{
+	const char *drng_type = unlikely(sdrng == &lrng_sdrng_atomic) ?
+				"atomic" : "secondary";
+	unsigned long flags = 0;
+
+	BUILD_BUG_ON(LRNG_DRNG_RESEED_THRESH > INT_MAX);
+	pr_debug("seeding %s DRNG with %u bytes\n", drng_type, inbuflen);
+	lrng_sdrng_lock(sdrng, &flags);
+	if (sdrng->crypto_cb->lrng_drng_seed_helper(sdrng->sdrng,
+						    inbuf, inbuflen) < 0) {
+		pr_warn("seeding of %s DRNG failed\n", drng_type);
+		atomic_set(&sdrng->requests, 1);
+	} else {
+		pr_debug("%s DRNG stats since last seeding: %lu secs; "
+			 "generate calls: %d\n", drng_type,
+			 (time_after(jiffies, sdrng->last_seeded) ?
+			  (jiffies - sdrng->last_seeded) : 0) / HZ,
+			 (LRNG_DRNG_RESEED_THRESH -
+			  atomic_read(&sdrng->requests)));
+		sdrng->last_seeded = jiffies;
+		atomic_set(&sdrng->requests, LRNG_DRNG_RESEED_THRESH);
+		sdrng->force_reseed = false;
+
+		if (sdrng->sdrng == lrng_sdrng_atomic.sdrng) {
+			lrng_sdrng_atomic.last_seeded = jiffies;
+			atomic_set(&lrng_sdrng_atomic.requests,
+				   LRNG_DRNG_RESEED_THRESH);
+			lrng_sdrng_atomic.force_reseed = false;
+		}
+	}
+	lrng_sdrng_unlock(sdrng, &flags);
+}
+
+#ifdef CONFIG_LRNG_TRNG_SUPPORT
+static inline int _lrng_sdrng_seed(struct lrng_sdrng *sdrng)
+{
+	u8 seedbuf[LRNG_DRNG_SECURITY_STRENGTH_BYTES]
+						__aligned(LRNG_KCAPI_ALIGN);
+	int ret = lrng_trng_seed(seedbuf, sizeof(seedbuf), false,
+				 !sdrng->fully_seeded);
+
+	/* Update the DRNG state even though we received zero random data */
+	if (ret < 0) {
+		/*
+		 * Try to reseed at next round - note if EINPROGRESS is returned
+		 * the request counter may fall below zero in case of parallel
+		 * operations. We accept such "underflow" temporarily as the
+		 * counter will be set back to a positive number in the course
+		 * of the reseed. For these few generate operations under
+		 * heavy parallel strain of /dev/urandom we therefore exceed
+		 * the LRNG_DRNG_RESEED_THRESH threshold.
+		 */
+		if (ret != -EINPROGRESS)
+			atomic_set(&sdrng->requests, 1);
+		return ret;
+	}
+
+	lrng_sdrng_inject(sdrng, seedbuf, sizeof(seedbuf));
+	memzero_explicit(seedbuf, sizeof(seedbuf));
+
+	return ret;
+}
+#else	/* CONFIG_LRNG_TRNG_SUPPORT */
+static inline int _lrng_sdrng_seed(struct lrng_sdrng *sdrng)
+{
+	struct entropy_buf seedbuf __aligned(LRNG_KCAPI_ALIGN);
+	unsigned long flags = 0;
+	u32 total_entropy_bits;
+	int ret;
+
+	lrng_sdrng_lock(sdrng, &flags);
+	total_entropy_bits = lrng_fill_seed_buffer(sdrng->crypto_cb,
+						   sdrng->hash, &seedbuf, true);
+	lrng_sdrng_unlock(sdrng, &flags);
+
+	/* Allow the seeding operation to be called again */
+	lrng_pool_unlock();
+	lrng_init_ops(total_entropy_bits);
+	ret = total_entropy_bits >> 3;
+
+	lrng_sdrng_inject(sdrng, (u8 *)&seedbuf, sizeof(seedbuf));
+	memzero_explicit(&seedbuf, sizeof(seedbuf));
+
+	return ret;
+}
+#endif	/* CONFIG_LRNG_TRNG_SUPPORT */
+
+static int lrng_sdrng_get(struct lrng_sdrng *sdrng, u8 *outbuf, u32 outbuflen);
+static void lrng_sdrng_seed(struct lrng_sdrng *sdrng)
+{
+	int ret = _lrng_sdrng_seed(sdrng);
+
+	if (ret >= LRNG_DRNG_SECURITY_STRENGTH_BYTES)
+		sdrng->fully_seeded = true;
+
+	BUILD_BUG_ON(LRNG_MIN_SEED_ENTROPY_BITS >
+		     LRNG_DRNG_SECURITY_STRENGTH_BITS);
+
+	/*
+	 * Reseed atomic DRNG from current secondary DRNG,
+	 *
+	 * We can obtain random numbers from secondary DRNG as the lock type
+	 * chosen by lrng_sdrng_get is usable with the current caller.
+	 */
+	if ((sdrng->sdrng != lrng_sdrng_atomic.sdrng) &&
+	    (lrng_sdrng_atomic.force_reseed ||
+	     atomic_read(&lrng_sdrng_atomic.requests) <= 0 ||
+	     time_after(jiffies, lrng_sdrng_atomic.last_seeded +
+			lrng_sdrng_reseed_max_time * HZ))) {
+		u8 seedbuf[LRNG_DRNG_SECURITY_STRENGTH_BYTES]
+						__aligned(LRNG_KCAPI_ALIGN);
+
+		ret = lrng_sdrng_get(sdrng, seedbuf, sizeof(seedbuf));
+
+		if (ret < 0) {
+			pr_warn("Error generating random numbers for atomic "
+				"DRNG: %d\n", ret);
+		} else {
+			lrng_sdrng_inject(&lrng_sdrng_atomic, seedbuf, ret);
+		}
+		memzero_explicit(&seedbuf, sizeof(seedbuf));
+	}
+}
+
+static inline void _lrng_sdrng_seed_work(struct lrng_sdrng *sdrng, u32 node)
+{
+	pr_debug("reseed triggered by interrupt noise source "
+		 "for secondary DRNG on NUMA node %d\n", node);
+	lrng_sdrng_seed(sdrng);
+	if (sdrng->fully_seeded) {
+		/* Prevent reseed storm */
+		sdrng->last_seeded += node * 100 * HZ;
+		/* Prevent draining of pool on idle systems */
+		lrng_sdrng_reseed_max_time += 100;
+	}
+}
+
+/**
+ * DRNG reseed trigger: Kernel thread handler triggered by the schedule_work()
+ */
+void lrng_sdrng_seed_work(struct work_struct *dummy)
+{
+	struct lrng_sdrng **lrng_sdrng = lrng_sdrng_instances();
+	u32 node;
+
+	if (lrng_sdrng) {
+		for_each_online_node(node) {
+			struct lrng_sdrng *sdrng = lrng_sdrng[node];
+
+			if (sdrng && !sdrng->fully_seeded) {
+				_lrng_sdrng_seed_work(sdrng, node);
+				goto out;
+			}
+		}
+		lrng_pool_all_numa_nodes_seeded();
+	} else {
+		if (!lrng_sdrng_init.fully_seeded)
+			_lrng_sdrng_seed_work(&lrng_sdrng_init, 0);
+	}
+
+out:
+	/* Allow the seeding operation to be called again */
+	lrng_pool_unlock();
+}
+
+/* Force all secondary DRNGs to reseed before next generation */
+void lrng_sdrng_force_reseed(void)
+{
+	struct lrng_sdrng **lrng_sdrng = lrng_sdrng_instances();
+	u32 node;
+
+	if (!lrng_sdrng) {
+		lrng_sdrng_init.force_reseed = true;
+		pr_debug("force reseed of initial secondary DRNG\n");
+		return;
+	}
+	for_each_online_node(node) {
+		struct lrng_sdrng *sdrng = lrng_sdrng[node];
+
+		if (!sdrng)
+			continue;
+
+		sdrng->force_reseed = true;
+		pr_debug("force reseed of secondary DRNG on node %u\n", node);
+	}
+	lrng_sdrng_atomic.force_reseed = true;
+}
+
+/**
+ * Get random data out of the secondary DRNG which is reseeded frequently.
+ *
+ * @outbuf: buffer for storing random data
+ * @outbuflen: length of outbuf
+ * @return: < 0 in error case (DRNG generation or update failed)
+ *	    >=0 returning the returned number of bytes
+ */
+static int lrng_sdrng_get(struct lrng_sdrng *sdrng, u8 *outbuf, u32 outbuflen)
+{
+	unsigned long flags = 0;
+	u32 processed = 0;
+
+	if (!outbuf || !outbuflen)
+		return 0;
+
+	outbuflen = min_t(size_t, outbuflen, INT_MAX);
+
+	lrng_drngs_init_cc20();
+
+	while (outbuflen) {
+		u32 todo = min_t(u32, outbuflen, LRNG_DRNG_MAX_REQSIZE);
+		int ret;
+
+		/* All but the atomic DRNG are seeded during generation */
+		if (atomic_dec_and_test(&sdrng->requests) ||
+		    sdrng->force_reseed ||
+		    time_after(jiffies, sdrng->last_seeded +
+			       lrng_sdrng_reseed_max_time * HZ)) {
+			if (likely(sdrng != &lrng_sdrng_atomic)) {
+				if (lrng_pool_trylock())
+					atomic_set(&sdrng->requests, 1);
+				else
+					lrng_sdrng_seed(sdrng);
+			}
+		}
+
+		lrng_sdrng_lock(sdrng, &flags);
+		ret = sdrng->crypto_cb->lrng_drng_generate_helper(
+					sdrng->sdrng, outbuf + processed, todo);
+		lrng_sdrng_unlock(sdrng, &flags);
+		if (ret <= 0) {
+			pr_warn("getting random data from secondary DRNG "
+				"failed (%d)\n", ret);
+			return -EFAULT;
+		}
+		processed += ret;
+		outbuflen -= ret;
+	}
+
+	return processed;
+}
+
+int lrng_sdrng_get_atomic(u8 *outbuf, u32 outbuflen)
+{
+	return lrng_sdrng_get(&lrng_sdrng_atomic, outbuf, outbuflen);
+}
+
+int lrng_sdrng_get_sleep(u8 *outbuf, u32 outbuflen)
+{
+	struct lrng_sdrng **lrng_sdrng = lrng_sdrng_instances();
+	struct lrng_sdrng *sdrng = &lrng_sdrng_init;
+	int node = numa_node_id();
+
+	might_sleep();
+
+	if (lrng_sdrng && lrng_sdrng[node] && lrng_sdrng[node]->fully_seeded)
+		sdrng = lrng_sdrng[node];
+
+	return lrng_sdrng_get(sdrng, outbuf, outbuflen);
+}
+
+/* Initialize the default DRNG during boot */
+void lrng_drngs_init_cc20(void)
+{
+	unsigned long flags = 0;
+
+	if (lrng_get_available())
+		return;
+
+	lrng_sdrng_lock(&lrng_sdrng_init, &flags);
+	if (lrng_get_available()) {
+		lrng_sdrng_unlock(&lrng_sdrng_init, &flags);
+		return;
+	}
+
+	if (random_get_entropy() || random_get_entropy()) {
+		/*
+		 * As the highres timer is identified here, previous interrupts
+		 * obtained during boot time are treated like a lowres-timer
+		 * would have been present.
+		 */
+		lrng_pool_configure(true, LRNG_IRQ_ENTROPY_BITS);
+	} else {
+		lrng_health_disable();
+		lrng_pool_configure(false, LRNG_IRQ_ENTROPY_BITS *
+					   LRNG_IRQ_OVERSAMPLING_FACTOR);
+		pr_warn("operating without high-resolution timer and applying "
+			"IRQ oversampling factor %u\n",
+			LRNG_IRQ_OVERSAMPLING_FACTOR);
+	}
+
+	lrng_sdrng_reset(&lrng_sdrng_init);
+	lrng_cc20_init_state(&secondary_chacha20);
+	lrng_state_init_seed_work();
+	lrng_sdrng_unlock(&lrng_sdrng_init, &flags);
+
+	lrng_sdrng_lock(&lrng_sdrng_atomic, &flags);
+	lrng_sdrng_reset(&lrng_sdrng_atomic);
+	/*
+	 * We do not initialize the state of the atomic DRNG as it is identical
+	 * to the secondary DRNG at this point.
+	 */
+	lrng_sdrng_unlock(&lrng_sdrng_atomic, &flags);
+
+	lrng_trng_init();
+
+	lrng_set_available();
+}
+
+/* Reset LRNG such that all existing entropy is gone */
+static void _lrng_reset(struct work_struct *work)
+{
+	struct lrng_sdrng **lrng_sdrng = lrng_sdrng_instances();
+	unsigned long flags = 0;
+
+	lrng_reset_state();
+	lrng_trng_reset();
+
+	if (!lrng_sdrng) {
+		lrng_sdrng_lock(&lrng_sdrng_init, &flags);
+		lrng_sdrng_reset(&lrng_sdrng_init);
+		lrng_sdrng_unlock(&lrng_sdrng_init, &flags);
+	} else {
+		u32 node;
+
+		for_each_online_node(node) {
+			struct lrng_sdrng *sdrng = lrng_sdrng[node];
+
+			if (!sdrng)
+				continue;
+			lrng_sdrng_lock(sdrng, &flags);
+			lrng_sdrng_reset(sdrng);
+			lrng_sdrng_unlock(sdrng, &flags);
+		}
+	}
+	lrng_set_entropy_thresh(LRNG_INIT_ENTROPY_BITS +
+				LRNG_CONDITIONING_ENTROPY_LOSS);
+}
+
+static DECLARE_WORK(lrng_reset_work, _lrng_reset);
+
+void lrng_reset(void)
+{
+	schedule_work(&lrng_reset_work);
+}
+
+/***************************** Initialize LRNG *******************************/
+
+static int __init lrng_init(void)
+{
+	lrng_drngs_init_cc20();
+
+	lrng_drngs_numa_alloc();
+	return 0;
+}
+
+late_initcall(lrng_init);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
+MODULE_DESCRIPTION("Linux Random Number Generator");
diff --git a/drivers/char/lrng/lrng_sw_noise.c b/drivers/char/lrng/lrng_sw_noise.c
new file mode 100644
index 000000000000..2d6e323e5f08
--- /dev/null
+++ b/drivers/char/lrng/lrng_sw_noise.c
@@ -0,0 +1,156 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG Slow Noise Source: Interrupt data collection
+ *
+ * Copyright (C) 2016 - 2019, Stephan Mueller <smueller@chronox.de>
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#include <asm/irq_regs.h>
+#include <linux/random.h>
+
+#include "lrng_internal.h"
+
+/*
+ * To limit the impact on the interrupt handling, the LRNG concatenates
+ * entropic LSB parts of the time stamps in a per-CPU array and only
+ * injects them into the entropy pool when the array is full.
+ */
+/* Number of time values to store in the array */
+#define LRNG_TIME_NUM_VALUES		(64)
+/* Mask of LSB of time stamp to store */
+#define LRNG_TIME_WORD_MASK		(LRNG_TIME_NUM_VALUES - 1)
+
+/* Store multiple integers in one u32 */
+#define LRNG_TIME_SLOTSIZE_BITS		(8)
+#define LRNG_TIME_SLOTSIZE_MASK		((1 << LRNG_TIME_SLOTSIZE_BITS) - 1)
+#define LRNG_TIME_ARRAY_MEMBER_BITS	(sizeof(u32) << 3)
+#define LRNG_TIME_SLOTS_PER_UINT	(LRNG_TIME_ARRAY_MEMBER_BITS / \
+					 LRNG_TIME_SLOTSIZE_BITS)
+#define LRNG_TIME_SLOTS_MASK		(LRNG_TIME_SLOTS_PER_UINT - 1)
+#define LRNG_TIME_ARRAY_SIZE		(LRNG_TIME_NUM_VALUES /	\
+					 LRNG_TIME_SLOTS_PER_UINT)
+
+/* Holder of time stamps before mixing them into the entropy pool */
+static DEFINE_PER_CPU(u32 [LRNG_TIME_ARRAY_SIZE], lrng_time);
+static DEFINE_PER_CPU(u32, lrng_time_ptr) = 0;
+static DEFINE_PER_CPU(u8, lrng_time_irqs) = 0;
+
+/* Starting bit index of slot */
+static inline unsigned int lrng_time_slot2bitindex(unsigned int slot)
+{
+	return (LRNG_TIME_SLOTSIZE_BITS * slot);
+}
+
+/* Convert index into the array index */
+static inline unsigned int lrng_time_idx2array(unsigned int idx)
+{
+	return idx / LRNG_TIME_SLOTS_PER_UINT;
+}
+
+/* Convert index into the slot of a given array index */
+static inline unsigned int lrng_time_idx2slot(unsigned int idx)
+{
+	return idx & LRNG_TIME_SLOTS_MASK;
+}
+
+/* Convert value into slot value */
+static inline unsigned int lrng_time_slot_val(unsigned int val,
+					      unsigned int slot)
+{
+	return val << lrng_time_slot2bitindex(slot);
+}
+
+/**
+ * Batching up of entropy in per-CPU array before injecting into entropy pool.
+ */
+static inline void lrng_time_process(void)
+{
+	u32 i, ptr, now_time = random_get_entropy() &
+			       (likely(lrng_state_fully_seeded()) ?
+				LRNG_TIME_SLOTSIZE_MASK : (u32)-1);
+	enum lrng_health_res health_test;
+
+	/* Ensure sufficient space in lrng_time_irqs */
+	BUILD_BUG_ON(LRNG_TIME_NUM_VALUES >= (1 << (sizeof(u8) << 3)));
+	BUILD_BUG_ON(LRNG_TIME_ARRAY_MEMBER_BITS % LRNG_TIME_SLOTSIZE_BITS);
+
+	if (lrng_raw_entropy_store(now_time))
+		return;
+
+	health_test = lrng_health_test(now_time);
+	if (health_test > lrng_health_fail_use)
+		return;
+
+	/* During boot time, we mix the full time stamp directly into LFSR */
+	if (unlikely(!lrng_state_fully_seeded())) {
+		lrng_pool_lfsr_u32(now_time);
+		if (health_test == lrng_health_pass)
+			lrng_pool_add_irq(1);
+		return;
+	}
+
+	ptr = this_cpu_inc_return(lrng_time_ptr) & LRNG_TIME_WORD_MASK;
+	this_cpu_or(lrng_time[lrng_time_idx2array(ptr)],
+		    lrng_time_slot_val(now_time & LRNG_TIME_SLOTSIZE_MASK,
+				       lrng_time_idx2slot(ptr)));
+
+	/* Interrupt delivers entropy if health test passes */
+	if (health_test == lrng_health_pass)
+		this_cpu_inc(lrng_time_irqs);
+
+	/* Only mix the buffer of time stamps into LFSR when wrapping */
+	if (ptr < LRNG_TIME_WORD_MASK)
+		return;
+
+	for (i = 0; i < LRNG_TIME_ARRAY_SIZE; i++) {
+		lrng_pool_lfsr_u32(this_cpu_read(lrng_time[i]));
+		this_cpu_write(lrng_time[i], 0);
+	}
+	lrng_pool_add_irq(this_cpu_read(lrng_time_irqs));
+	this_cpu_write(lrng_time_irqs, 0);
+}
+
+/**
+ * Hot code path - Callback for interrupt handler
+ */
+void add_interrupt_randomness(int irq, int irq_flags)
+{
+	lrng_time_process();
+
+	if (!lrng_pool_highres_timer()) {
+		struct pt_regs *regs = get_irq_regs();
+		static atomic_t reg_idx = ATOMIC_INIT(0);
+		u64 ip;
+
+		lrng_pool_lfsr_u32(jiffies);
+		lrng_pool_lfsr_u32(irq);
+		lrng_pool_lfsr_u32(irq_flags);
+
+		if (regs) {
+			u32 *ptr = (u32 *)regs;
+			int reg_ptr = atomic_add_return_relaxed(1, &reg_idx);
+			size_t n = (sizeof(struct pt_regs) / sizeof(u32));
+
+			ip = instruction_pointer(regs);
+			lrng_pool_lfsr_u32(*(ptr + (reg_ptr % n)));
+		} else
+			ip = _RET_IP_;
+
+		lrng_pool_lfsr_u32(ip >> 32);
+		lrng_pool_lfsr_u32(ip);
+	}
+}
+EXPORT_SYMBOL(add_interrupt_randomness);
diff --git a/include/linux/lrng.h b/include/linux/lrng.h
new file mode 100644
index 000000000000..2ece3a66e0f5
--- /dev/null
+++ b/include/linux/lrng.h
@@ -0,0 +1,83 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
+/*
+ * Copyright (C) 2018 - 2019, Stephan Mueller <smueller@chronox.de>
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#ifndef _LRNG_H
+#define _LRNG_H
+
+#include <linux/types.h>
+
+/**
+ * struct lrng_crypto_cb - cryptographic callback functions
+ * @lrng_drng_name		Name of DRNG
+ * @lrng_hash_name		Name of Hash used for reading entropy pool
+ * @lrng_drng_alloc:		Allocate DRNG -- the provided integer should be
+ *				used for sanity checks.
+ *				return: allocated data structure or PTR_ERR on
+ *					error
+ * @lrng_drng_dealloc:		Deallocate DRNG
+ * @lrng_drng_seed_helper:	Seed the DRNG with data of arbitrary length
+ *				drng: is pointer to data structure allocated
+ *				      with lrng_drng_alloc
+ *				return: >= 0 on success, < 0 on error
+ * @lrng_drng_generate_helper:	Generate random numbers from the DRNG with
+ *				arbitrary length
+ * @lrng_drng_generate_helper_full: Generate random numbers from the DRNG with
+ *				    arbitrary length where the output is
+ *				    capable of providing 1 bit of entropy per
+ *				    data bit.
+ *				    return: generated number of bytes,
+ *					    < 0 on error
+ * @lrng_hash_alloc:		Allocate the hash for reading the entropy pool
+ *				return: allocated data structure (NULL is
+ *					success too) or ERR_PTR on error
+ * @lrng_hash_dealloc:		Deallocate Hash
+ * @lrng_hash_digestsize:	Return the digestsize for the used hash to read
+ *				out entropy pool
+ *				hash: is pointer to data structure allocated
+ *				      with lrng_hash_alloc
+ *				return: size of digest of hash in bytes
+ * @lrng_hash_buffer:		Generate hash
+ *				hash: is pointer to data structure allocated
+ *				      with lrng_hash_alloc
+ *				return: 0 on success, < 0 on error
+ */
+struct lrng_crypto_cb {
+	const char *(*lrng_drng_name)(void);
+	const char *(*lrng_hash_name)(void);
+	void *(*lrng_drng_alloc)(u32 sec_strength);
+	void (*lrng_drng_dealloc)(void *drng);
+	int (*lrng_drng_seed_helper)(void *drng, const u8 *inbuf, u32 inbuflen);
+	int (*lrng_drng_generate_helper)(void *drng, u8 *outbuf, u32 outbuflen);
+	int (*lrng_drng_generate_helper_full)(void *drng, u8 *outbuf,
+					      u32 outbuflen);
+	void *(*lrng_hash_alloc)(const u8 *key, u32 keylen);
+	void (*lrng_hash_dealloc)(void *hash);
+	u32 (*lrng_hash_digestsize)(void *hash);
+	int (*lrng_hash_buffer)(void *hash, const u8 *inbuf, u32 inbuflen,
+				u8 *digest);
+};
+
+/* Register cryptographic backend */
+#ifdef CONFIG_LRNG_DRNG_SWITCH
+int lrng_set_drng_cb(const struct lrng_crypto_cb *cb);
+#else	/* CONFIG_LRNG_DRNG_SWITCH */
+static inline int
+lrng_set_drng_cb(const struct lrng_crypto_cb *cb) { return -EOPNOTSUPP; }
+#endif	/* CONFIG_LRNG_DRNG_SWITCH */
+
+#endif /* _LRNG_H */
-- 
2.23.0





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v24 02/12] LRNG - allocate one SDRNG instance per NUMA node
  2019-11-11 18:17 [PATCH v24 00/12] /dev/random - a new approach with full SP800-90B compliance Stephan Müller
  2019-11-11 18:18 ` [PATCH v24 01/12] Linux Random Number Generator Stephan Müller
@ 2019-11-11 18:19 ` Stephan Müller
  2019-11-11 18:20 ` [PATCH v24 03/12] LRNG - /proc interface Stephan Müller
                   ` (12 subsequent siblings)
  14 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-11 18:19 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

In order to improve NUMA-locality when serving getrandom(2) requests,
allocate one DRNG instance per node.

The SDRNG instance that is present right from the start of the kernel is
reused as the first per-NUMA-node SDRNG. For all remaining online NUMA
nodes a new SDRNG instance is allocated.

During boot time, the multiple SDRNG instances are seeded sequentially.
With this, the first SDRNG instance (referenced as the initial SDRNG
in the code) is completely seeded with 256 bits of entropy before the
next SDRNG instance is completely seeded.

When random numbers are requested, the NUMA-node-local SDRNG is checked
whether it has been already fully seeded. If this is not the case, the
initial SDRNG is used to serve the request.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Makefile        |   2 +
 drivers/char/lrng/lrng_internal.h |   5 ++
 drivers/char/lrng/lrng_numa.c     | 114 ++++++++++++++++++++++++++++++
 3 files changed, 121 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_numa.c

diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index 2761623715d2..a00cddb45773 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -7,3 +7,5 @@ obj-y				+= lrng_pool.o lrng_aux.o \
 				   lrng_sw_noise.o lrng_archrandom.o \
 				   lrng_sdrng.o lrng_chacha20.o \
 				   lrng_interfaces.o \
+
+obj-$(CONFIG_NUMA)		+= lrng_numa.o
diff --git a/drivers/char/lrng/lrng_internal.h b/drivers/char/lrng/lrng_internal.h
index 242f9b5b4f3d..e6ac2c527378 100644
--- a/drivers/char/lrng/lrng_internal.h
+++ b/drivers/char/lrng/lrng_internal.h
@@ -263,8 +263,13 @@ int lrng_sdrng_get_sleep(u8 *outbuf, u32 outbuflen);
 void lrng_sdrng_force_reseed(void);
 void lrng_sdrng_seed_work(struct work_struct *dummy);
 
+#ifdef CONFIG_NUMA
+struct lrng_sdrng **lrng_sdrng_instances(void);
+void lrng_drngs_numa_alloc(void);
+#else	/* CONFIG_NUMA */
 static inline struct lrng_sdrng **lrng_sdrng_instances(void) { return NULL; }
 static inline void lrng_drngs_numa_alloc(void) { return; }
+#endif /* CONFIG_NUMA */
 
 /************************** Health Test linking code **************************/
 
diff --git a/drivers/char/lrng/lrng_numa.c b/drivers/char/lrng/lrng_numa.c
new file mode 100644
index 000000000000..e88de91cb0aa
--- /dev/null
+++ b/drivers/char/lrng/lrng_numa.c
@@ -0,0 +1,114 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG NUMA support
+ *
+ * Copyright (C) 2016 - 2019, Stephan Mueller <smueller@chronox.de>
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/lrng.h>
+#include <linux/slab.h>
+
+#include "lrng_internal.h"
+
+static struct lrng_sdrng **lrng_sdrng __read_mostly = NULL;
+
+struct lrng_sdrng **lrng_sdrng_instances(void)
+{
+	return lrng_sdrng;
+}
+
+/* Allocate the data structures for the per-NUMA node DRNGs */
+static void _lrng_drngs_numa_alloc(struct work_struct *work)
+{
+	struct lrng_sdrng **sdrngs;
+	struct lrng_sdrng *lrng_sdrng_init = lrng_sdrng_init_instance();
+	u32 node;
+	bool init_sdrng_used = false;
+
+	mutex_lock(&lrng_crypto_cb_update);
+
+	/* per-NUMA-node DRNGs are already present */
+	if (lrng_sdrng)
+		goto unlock;
+
+	sdrngs = kcalloc(nr_node_ids, sizeof(void *), GFP_KERNEL|__GFP_NOFAIL);
+	for_each_online_node(node) {
+		struct lrng_sdrng *sdrng;
+
+		if (!init_sdrng_used) {
+			sdrngs[node] = lrng_sdrng_init;
+			init_sdrng_used = true;
+			continue;
+		}
+
+		sdrng = kmalloc_node(sizeof(struct lrng_sdrng),
+				     GFP_KERNEL|__GFP_NOFAIL, node);
+		memset(sdrng, 0, sizeof(lrng_sdrng));
+
+		sdrng->crypto_cb = lrng_sdrng_init->crypto_cb;
+		sdrng->sdrng = sdrng->crypto_cb->lrng_drng_alloc(
+					LRNG_DRNG_SECURITY_STRENGTH_BYTES);
+		if (IS_ERR(sdrng->sdrng)) {
+			kfree(sdrng);
+			goto err;
+		}
+
+		mutex_init(&sdrng->lock);
+		spin_lock_init(&sdrng->spin_lock);
+
+		/*
+		 * No reseeding of NUMA DRNGs from previous DRNGs as this
+		 * would complicate the code. Let it simply reseed.
+		 */
+		lrng_sdrng_reset(sdrng);
+		sdrngs[node] = sdrng;
+
+		lrng_pool_inc_numa_node();
+		pr_info("secondary DRNG for NUMA node %d allocated\n", node);
+	}
+
+	/* Ensure that all NUMA nodes receive changed memory here. */
+	mb();
+
+	if (!cmpxchg(&lrng_sdrng, NULL, sdrngs))
+		goto unlock;
+
+err:
+	for_each_online_node(node) {
+		struct lrng_sdrng *sdrng = sdrngs[node];
+
+		if (sdrng == lrng_sdrng_init)
+			continue;
+
+		if (sdrng) {
+			sdrng->crypto_cb->lrng_drng_dealloc(sdrng->sdrng);
+			kfree(sdrng);
+		}
+	}
+	kfree(sdrngs);
+
+unlock:
+	mutex_unlock(&lrng_crypto_cb_update);
+}
+
+static DECLARE_WORK(lrng_drngs_numa_alloc_work, _lrng_drngs_numa_alloc);
+
+void lrng_drngs_numa_alloc(void)
+{
+	schedule_work(&lrng_drngs_numa_alloc_work);
+}
-- 
2.23.0





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v24 03/12] LRNG - /proc interface
  2019-11-11 18:17 [PATCH v24 00/12] /dev/random - a new approach with full SP800-90B compliance Stephan Müller
  2019-11-11 18:18 ` [PATCH v24 01/12] Linux Random Number Generator Stephan Müller
  2019-11-11 18:19 ` [PATCH v24 02/12] LRNG - allocate one SDRNG instance per NUMA node Stephan Müller
@ 2019-11-11 18:20 ` Stephan Müller
  2019-11-11 18:20 ` [PATCH v24 04/12] LRNG - add switchable DRNG support Stephan Müller
                   ` (11 subsequent siblings)
  14 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-11 18:20 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

The LRNG /proc interface provides the same files as the legacy
/dev/random. These files behave identically. Yet, all files are
documented at [1].

In addition, it provides the file lrng_type which provides details about
the LRNG:

- is the TRNG present

- the name of the DRNG that produces the random numbers for /dev/random,
/dev/urandom, getrandom(2)

- the hash used to produce random numbers from the entropy pool

- the number of secondary DRNG instances

- indicator whether the LRNG operates SP800-90B compliant

- indicator whether a high-resolution timer is identified - only with a
high-resolution timer the interrupt noise source will deliver sufficient
entropy

- indicator whether the LRNG has been minimally seeded (i.e. is the
secondary DRNG seeded with at least 128 bits of of entropy)

- indicator whether the LRNG has been fully seeded (i.e. is the
secondary DRNG seeded with at least 256 bits of entropy)

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

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Makefile          |   1 +
 drivers/char/lrng/lrng_interfaces.c |   1 -
 drivers/char/lrng/lrng_internal.h   |   4 +
 drivers/char/lrng/lrng_proc.c       | 192 ++++++++++++++++++++++++++++
 4 files changed, 197 insertions(+), 1 deletion(-)
 create mode 100644 drivers/char/lrng/lrng_proc.c

diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index a00cddb45773..b6240b73e33d 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -9,3 +9,4 @@ obj-y				+= lrng_pool.o lrng_aux.o \
 				   lrng_interfaces.o \
 
 obj-$(CONFIG_NUMA)		+= lrng_numa.o
+obj-$(CONFIG_SYSCTL)		+= lrng_proc.o
diff --git a/drivers/char/lrng/lrng_interfaces.c b/drivers/char/lrng/lrng_interfaces.c
index e652849a1bdb..1c9517c6df4a 100644
--- a/drivers/char/lrng/lrng_interfaces.c
+++ b/drivers/char/lrng/lrng_interfaces.c
@@ -56,7 +56,6 @@ static DECLARE_WAIT_QUEUE_HEAD(lrng_write_wait);
 static DECLARE_WAIT_QUEUE_HEAD(lrng_init_wait);
 static struct fasync_struct *fasync;
 
-struct ctl_table random_table[];
 /********************************** Helper ***********************************/
 
 /* Is the primary DRNG seed level too low? */
diff --git a/drivers/char/lrng/lrng_internal.h b/drivers/char/lrng/lrng_internal.h
index e6ac2c527378..8528c2e8de88 100644
--- a/drivers/char/lrng/lrng_internal.h
+++ b/drivers/char/lrng/lrng_internal.h
@@ -116,7 +116,11 @@ void lrng_cc20_init_state(struct chacha20_state *state);
 
 /********************************** /proc *************************************/
 
+#ifdef CONFIG_SYSCTL
+void lrng_pool_inc_numa_node(void);
+#else
 static inline void lrng_pool_inc_numa_node(void) { }
+#endif
 
 /****************************** LRNG interfaces *******************************/
 
diff --git a/drivers/char/lrng/lrng_proc.c b/drivers/char/lrng/lrng_proc.c
new file mode 100644
index 000000000000..0e67dd4e5901
--- /dev/null
+++ b/drivers/char/lrng/lrng_proc.c
@@ -0,0 +1,192 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG proc interfaces
+ *
+ * Copyright (C) 2016 - 2019, Stephan Mueller <smueller@chronox.de>
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#include <linux/lrng.h>
+#include <linux/sysctl.h>
+#include <linux/uuid.h>
+
+#include "lrng_internal.h"
+
+/* Number of online DRNGs */
+static u32 numa_drngs = 1;
+
+void lrng_pool_inc_numa_node(void)
+{
+	numa_drngs++;
+}
+
+/*
+ * This function is used to return both the bootid UUID, and random
+ * UUID.  The difference is in whether table->data is NULL; if it is,
+ * then a new UUID is generated and returned to the user.
+ *
+ * If the user accesses this via the proc interface, the UUID will be
+ * returned as an ASCII string in the standard UUID format; if via the
+ * sysctl system call, as 16 bytes of binary data.
+ */
+static int lrng_proc_do_uuid(struct ctl_table *table, int write,
+			     void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	struct ctl_table fake_table;
+	unsigned char buf[64], tmp_uuid[16], *uuid;
+
+	uuid = table->data;
+	if (!uuid) {
+		uuid = tmp_uuid;
+		generate_random_uuid(uuid);
+	} else {
+		static DEFINE_SPINLOCK(bootid_spinlock);
+
+		spin_lock(&bootid_spinlock);
+		if (!uuid[8])
+			generate_random_uuid(uuid);
+		spin_unlock(&bootid_spinlock);
+	}
+
+	sprintf(buf, "%pU", uuid);
+
+	fake_table.data = buf;
+	fake_table.maxlen = sizeof(buf);
+
+	return proc_dostring(&fake_table, write, buffer, lenp, ppos);
+}
+
+static int lrng_proc_do_type(struct ctl_table *table, int write,
+			     void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	struct lrng_sdrng *lrng_sdrng_init = lrng_sdrng_init_instance();
+	struct ctl_table fake_table;
+	unsigned long flags = 0;
+	unsigned char buf[300];
+
+	lrng_sdrng_lock(lrng_sdrng_init, &flags);
+	snprintf(buf, sizeof(buf),
+#ifdef CONFIG_LRNG_TRNG_SUPPORT
+		 "TRNG present: true\n"
+#else
+		 "TRNG present: false\n"
+#endif
+		 "DRNG name: %s\n"
+		 "Hash for reading entropy pool: %s\n"
+		 "DRNG security strength: %d bits\n"
+		 "number of secondary DRNG instances: %u\n"
+		 "SP800-90B compliance: %s\n"
+		 "High-resolution timer: %s\n"
+		 "LRNG minimally seeded: %s\n"
+		 "LRNG fully seeded: %s",
+		 lrng_sdrng_init->crypto_cb->lrng_drng_name(),
+		 lrng_sdrng_init->crypto_cb->lrng_hash_name(),
+		 LRNG_DRNG_SECURITY_STRENGTH_BITS, numa_drngs,
+		 lrng_sp80090b_compliant() ? "true" : "false",
+		 lrng_pool_highres_timer() ? "true" : "false",
+		 lrng_state_min_seeded() ? "true" : "false",
+		 lrng_state_fully_seeded() ? "true" : "false");
+	lrng_sdrng_unlock(lrng_sdrng_init, &flags);
+
+	fake_table.data = buf;
+	fake_table.maxlen = sizeof(buf);
+
+	return proc_dostring(&fake_table, write, buffer, lenp, ppos);
+}
+
+static int lrng_proc_do_entropy(struct ctl_table *table, int write,
+				void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	struct ctl_table fake_table;
+	int entropy_count;
+
+	entropy_count = lrng_avail_entropy();
+
+	fake_table.data = &entropy_count;
+	fake_table.maxlen = sizeof(entropy_count);
+
+	return proc_dointvec(&fake_table, write, buffer, lenp, ppos);
+}
+
+static int lrng_sysctl_poolsize = LRNG_POOL_SIZE_BITS;
+static int lrng_min_read_thresh = LRNG_POOL_WORD_BITS;
+static int lrng_min_write_thresh;
+static int lrng_max_read_thresh = LRNG_POOL_SIZE_BITS;
+static int lrng_max_write_thresh = LRNG_POOL_SIZE_BITS;
+static char lrng_sysctl_bootid[16];
+static int lrng_sdrng_reseed_max_min;
+
+extern struct ctl_table random_table[];
+struct ctl_table random_table[] = {
+	{
+		.procname	= "poolsize",
+		.data		= &lrng_sysctl_poolsize,
+		.maxlen		= sizeof(int),
+		.mode		= 0444,
+		.proc_handler	= proc_dointvec,
+	},
+	{
+		.procname	= "entropy_avail",
+		.maxlen		= sizeof(int),
+		.mode		= 0444,
+		.proc_handler	= lrng_proc_do_entropy,
+	},
+	{
+		.procname	= "read_wakeup_threshold",
+		.data		= &lrng_read_wakeup_bits,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec_minmax,
+		.extra1		= &lrng_min_read_thresh,
+		.extra2		= &lrng_max_read_thresh,
+	},
+	{
+		.procname	= "write_wakeup_threshold",
+		.data		= &lrng_write_wakeup_bits,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec_minmax,
+		.extra1		= &lrng_min_write_thresh,
+		.extra2		= &lrng_max_write_thresh,
+	},
+	{
+		.procname	= "boot_id",
+		.data		= &lrng_sysctl_bootid,
+		.maxlen		= 16,
+		.mode		= 0444,
+		.proc_handler	= lrng_proc_do_uuid,
+	},
+	{
+		.procname	= "uuid",
+		.maxlen		= 16,
+		.mode		= 0444,
+		.proc_handler	= lrng_proc_do_uuid,
+	},
+	{
+		.procname       = "urandom_min_reseed_secs",
+		.data           = &lrng_sdrng_reseed_max_time,
+		.maxlen         = sizeof(int),
+		.mode           = 0644,
+		.proc_handler   = proc_dointvec,
+		.extra1		= &lrng_sdrng_reseed_max_min,
+	},
+	{
+		.procname	= "lrng_type",
+		.maxlen		= 30,
+		.mode		= 0444,
+		.proc_handler	= lrng_proc_do_type,
+	},
+	{ }
+};
-- 
2.23.0





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v24 04/12] LRNG - add switchable DRNG support
  2019-11-11 18:17 [PATCH v24 00/12] /dev/random - a new approach with full SP800-90B compliance Stephan Müller
                   ` (2 preceding siblings ...)
  2019-11-11 18:20 ` [PATCH v24 03/12] LRNG - /proc interface Stephan Müller
@ 2019-11-11 18:20 ` Stephan Müller
  2019-11-11 18:21 ` [PATCH v24 05/12] crypto: DRBG - externalize DRBG functions for LRNG Stephan Müller
                   ` (10 subsequent siblings)
  14 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-11 18:20 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

The DRNG switch support allows replacing the DRNG mechanism of the
LRNG. The switching support rests on the interface definition of
include/linux/lrng.h. A new DRNG is implemented by filling in the
interface defined in this header file.

In addition to the DRNG, the extension also has to provide a hash
implementation that is used to hash the entropy pool for random number
extraction.

Note: It is permissible to implement a DRNG whose operations may sleep.
However, the hash function must not sleep.

The switchable DRNG support allows replacing the DRNG at runtime.
However, only one DRNG extension is allowed to be loaded at any given
time. Before replacing it with another DRNG implementation, the possibly
existing DRNG extension must be unloaded.

The switchable DRNG extension activates the new DRNG during load time.
It is expected, however, that such a DRNG switch would be done only once
by an administrator to load the intended DRNG implementation.

It is permissible to compile DRNG extensions either as kernel modules or
statically. The initialization of the DRNG extension should be performed
with a late_initcall to ensure the extension is available when user
space starts but after all other initialization completed.
The initialization is performed by registering the function call data
structure with the lrng_set_drng_cb function. In order to unload the
DRNG extension, lrng_set_drng_cb must be invoked with the NULL
parameter.

The DRNG extension should always provide a security strength that is at
least as strong as LRNG_DRNG_SECURITY_STRENGTH_BITS.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Kconfig       |   7 ++
 drivers/char/lrng/Makefile      |   1 +
 drivers/char/lrng/lrng_switch.c | 198 ++++++++++++++++++++++++++++++++
 3 files changed, 206 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_switch.c

diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
index edf8be6aa0b1..a468d8292bac 100644
--- a/drivers/char/lrng/Kconfig
+++ b/drivers/char/lrng/Kconfig
@@ -52,4 +52,11 @@ config LRNG_POOL_SIZE
 	default 4 if LRNG_POOL_SIZE_65536
 	default 5 if LRNG_POOL_SIZE_131072
 
+menuconfig LRNG_DRNG_SWITCH
+	bool "Support DRNG runtime switching"
+	help
+	  The Linux RNG per default uses a ChaCha20 DRNG that is
+	  accessible via the external interfaces. With this configuration
+	  option other DRNGs can be selected and loaded at runtime.
+
 endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index b6240b73e33d..6bac97638767 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -10,3 +10,4 @@ obj-y				+= lrng_pool.o lrng_aux.o \
 
 obj-$(CONFIG_NUMA)		+= lrng_numa.o
 obj-$(CONFIG_SYSCTL)		+= lrng_proc.o
+obj-$(CONFIG_LRNG_DRNG_SWITCH)	+= lrng_switch.o
diff --git a/drivers/char/lrng/lrng_switch.c b/drivers/char/lrng/lrng_switch.c
new file mode 100644
index 000000000000..55eb4ed73258
--- /dev/null
+++ b/drivers/char/lrng/lrng_switch.c
@@ -0,0 +1,198 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG DRNG switching support
+ *
+ * Copyright (C) 2016 - 2019, Stephan Mueller <smueller@chronox.de>
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/lrng.h>
+
+#include "lrng_internal.h"
+
+static void lrng_sdrng_switch(struct lrng_sdrng *sdrng_store,
+			      const struct lrng_crypto_cb *cb, int node)
+{
+	const struct lrng_crypto_cb *old_cb;
+	unsigned long flags = 0;
+	int ret;
+	u8 seed[LRNG_DRNG_SECURITY_STRENGTH_BYTES];
+	void *new_sdrng =
+			cb->lrng_drng_alloc(LRNG_DRNG_SECURITY_STRENGTH_BYTES);
+	void *old_sdrng, *new_hash = NULL, *old_hash = NULL;
+	bool sl = false, reset_sdrng = !lrng_get_available();
+
+	if (IS_ERR(new_sdrng)) {
+		pr_warn("could not allocate new secondary DRNG for NUMA node "
+			"%d (%ld)\n", node, PTR_ERR(new_sdrng));
+		return;
+	}
+
+#ifndef CONFIG_LRNG_TRNG_SUPPORT
+	new_hash = cb->lrng_hash_alloc(seed, sizeof(seed));
+#endif	/* CONFIG_LRNG_TRNG_SUPPORT */
+	if (IS_ERR(new_hash)) {
+		pr_warn("could not allocate new LRNG pool hash (%ld)\n",
+			PTR_ERR(new_hash));
+		cb->lrng_drng_dealloc(new_sdrng);
+		return;
+	}
+
+	lrng_sdrng_lock(sdrng_store, &flags);
+
+	/*
+	 * Pull from existing DRNG to seed new DRNG regardless of seed status
+	 * of old DRNG -- the entropy state for the secondary DRNG is left
+	 * unchanged which implies that als the new DRNG is reseeded when deemed
+	 * necessary. This seeding of the new DRNG shall only ensure that the
+	 * new DRNG has the same entropy as the old DRNG.
+	 */
+	ret = sdrng_store->crypto_cb->lrng_drng_generate_helper(
+				sdrng_store->sdrng, seed, sizeof(seed));
+	lrng_sdrng_unlock(sdrng_store, &flags);
+
+	if (ret < 0) {
+		reset_sdrng = true;
+		pr_warn("getting random data from secondary DRNG failed for "
+			"NUMA node %d (%d)\n", node, ret);
+	} else {
+		/* seed new DRNG with data */
+		ret = cb->lrng_drng_seed_helper(new_sdrng, seed, ret);
+		if (ret < 0) {
+			reset_sdrng = true;
+			pr_warn("seeding of new secondary DRNG failed for NUMA "
+				"node %d (%d)\n", node, ret);
+		} else {
+			pr_debug("seeded new secondary DRNG of NUMA node %d "
+				 "instance from old secondary DRNG instance\n",
+				 node);
+		}
+	}
+
+	mutex_lock(&sdrng_store->lock);
+	/*
+	 * If we switch the secondary DRNG from the initial ChaCha20 DRNG to
+	 * something else, there is a lock transition from spin lock to mutex
+	 * (see lrng_sdrng_is_atomic and how the lock is taken in
+	 * lrng_sdrng_lock). Thus, we need to take both locks during the
+	 * transition phase.
+	 */
+	if (lrng_sdrng_is_atomic(sdrng_store)) {
+		spin_lock_irqsave(&sdrng_store->spin_lock, flags);
+		sl = true;
+	}
+
+	if (reset_sdrng)
+		lrng_sdrng_reset(sdrng_store);
+
+	old_sdrng = sdrng_store->sdrng;
+	old_cb = sdrng_store->crypto_cb;
+	sdrng_store->sdrng = new_sdrng;
+	sdrng_store->crypto_cb = cb;
+
+	if (new_hash) {
+		old_hash = sdrng_store->hash;
+		sdrng_store->hash = new_hash;
+		pr_info("Entropy pool read-hash allocated for DRNG for NUMA "
+			"node %d\n", node);
+	}
+
+	if (sl)
+		spin_unlock_irqrestore(&sdrng_store->spin_lock, flags);
+	mutex_unlock(&sdrng_store->lock);
+
+	/* Secondary ChaCha20 serves as atomic instance left untouched. */
+	if (old_sdrng != &secondary_chacha20) {
+		old_cb->lrng_drng_dealloc(old_sdrng);
+		if (old_hash)
+			old_cb->lrng_hash_dealloc(old_hash);
+	}
+
+	pr_info("secondary DRNG of NUMA node %d switched\n", node);
+}
+
+/**
+ * Switch the existing DRNG instances with new using the new crypto callbacks.
+ * The caller must hold the lrng_crypto_cb_update lock.
+ */
+static int lrng_drngs_switch(const struct lrng_crypto_cb *cb)
+{
+	struct lrng_sdrng **lrng_sdrng = lrng_sdrng_instances();
+	struct lrng_sdrng *lrng_sdrng_init = lrng_sdrng_init_instance();
+	int ret = lrng_trng_switch(cb);
+
+	if (ret)
+		return ret;
+
+	/* Update secondary DRNG */
+	if (lrng_sdrng) {
+		u32 node;
+
+		for_each_online_node(node) {
+			if (lrng_sdrng[node])
+				lrng_sdrng_switch(lrng_sdrng[node], cb, node);
+		}
+	} else
+		lrng_sdrng_switch(lrng_sdrng_init, cb, 0);
+
+	lrng_set_available();
+
+	return 0;
+}
+
+/**
+ * lrng_set_drng_cb - Register new cryptographic callback functions for DRNG
+ * The registering implies that all old DRNG states are replaced with new
+ * DRNG states.
+ * @cb: Callback functions to be registered -- if NULL, use the default
+ *	callbacks pointing to the ChaCha20 DRNG.
+ * @return: 0 on success, < 0 on error
+ */
+int lrng_set_drng_cb(const struct lrng_crypto_cb *cb)
+{
+	struct lrng_sdrng *lrng_sdrng_init = lrng_sdrng_init_instance();
+	int ret;
+
+	if (!cb)
+		cb = &lrng_cc20_crypto_cb;
+
+	mutex_lock(&lrng_crypto_cb_update);
+
+	/*
+	 * If a callback other than the default is set, allow it only to be
+	 * set back to the default callback. This ensures that multiple
+	 * different callbacks can be registered at the same time. If a
+	 * callback different from the current callback and the default
+	 * callback shall be set, the current callback must be deregistered
+	 * (e.g. the kernel module providing it must be unloaded) and the new
+	 * implementation can be registered.
+	 */
+	if ((cb != &lrng_cc20_crypto_cb) &&
+	    (lrng_sdrng_init->crypto_cb != &lrng_cc20_crypto_cb)) {
+		pr_warn("disallow setting new cipher callbacks, unload the old "
+			"callbacks first!\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	ret = lrng_drngs_switch(cb);
+
+out:
+	mutex_unlock(&lrng_crypto_cb_update);
+	return ret;
+}
+EXPORT_SYMBOL(lrng_set_drng_cb);
-- 
2.23.0





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v24 05/12] crypto: DRBG - externalize DRBG functions for LRNG
  2019-11-11 18:17 [PATCH v24 00/12] /dev/random - a new approach with full SP800-90B compliance Stephan Müller
                   ` (3 preceding siblings ...)
  2019-11-11 18:20 ` [PATCH v24 04/12] LRNG - add switchable DRNG support Stephan Müller
@ 2019-11-11 18:21 ` Stephan Müller
  2019-11-11 18:21 ` [PATCH v24 06/12] LRNG - add SP800-90A DRBG extension Stephan Müller
                   ` (9 subsequent siblings)
  14 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-11 18:21 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

This patch allows several DRBG functions to be called by the LRNG kernel
code paths outside the drbg.c file.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 crypto/drbg.c         | 16 ++++++++++------
 include/crypto/drbg.h |  7 +++++++
 2 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/crypto/drbg.c b/crypto/drbg.c
index b6929eb5f565..5561dd0f09e1 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -113,7 +113,7 @@
  * the SHA256 / AES 256 over other ciphers. Thus, the favored
  * DRBGs are the latest entries in this array.
  */
-static const struct drbg_core drbg_cores[] = {
+const struct drbg_core drbg_cores[] = {
 #ifdef CONFIG_CRYPTO_DRBG_CTR
 	{
 		.flags = DRBG_CTR | DRBG_STRENGTH128,
@@ -190,6 +190,7 @@ static const struct drbg_core drbg_cores[] = {
 	},
 #endif /* CONFIG_CRYPTO_DRBG_HMAC */
 };
+EXPORT_SYMBOL(drbg_cores);
 
 static int drbg_uninstantiate(struct drbg_state *drbg);
 
@@ -205,7 +206,7 @@ static int drbg_uninstantiate(struct drbg_state *drbg);
  * Return: normalized strength in *bytes* value or 32 as default
  *	   to counter programming errors
  */
-static inline unsigned short drbg_sec_strength(drbg_flag_t flags)
+unsigned short drbg_sec_strength(drbg_flag_t flags)
 {
 	switch (flags & DRBG_STRENGTH_MASK) {
 	case DRBG_STRENGTH128:
@@ -218,6 +219,7 @@ static inline unsigned short drbg_sec_strength(drbg_flag_t flags)
 		return 32;
 	}
 }
+EXPORT_SYMBOL(drbg_sec_strength);
 
 /*
  * FIPS 140-2 continuous self test for the noise source
@@ -1202,7 +1204,7 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
 }
 
 /* Free all substructures in a DRBG state without the DRBG state structure */
-static inline void drbg_dealloc_state(struct drbg_state *drbg)
+void drbg_dealloc_state(struct drbg_state *drbg)
 {
 	if (!drbg)
 		return;
@@ -1223,12 +1225,13 @@ static inline void drbg_dealloc_state(struct drbg_state *drbg)
 		drbg->fips_primed = false;
 	}
 }
+EXPORT_SYMBOL(drbg_dealloc_state);
 
 /*
  * Allocate all sub-structures for a DRBG state.
  * The DRBG state structure must already be allocated.
  */
-static inline int drbg_alloc_state(struct drbg_state *drbg)
+int drbg_alloc_state(struct drbg_state *drbg)
 {
 	int ret = -ENOMEM;
 	unsigned int sb_size = 0;
@@ -1307,6 +1310,7 @@ static inline int drbg_alloc_state(struct drbg_state *drbg)
 	drbg_dealloc_state(drbg);
 	return ret;
 }
+EXPORT_SYMBOL(drbg_alloc_state);
 
 /*************************************************************************
  * DRBG interface functions
@@ -1874,8 +1878,7 @@ static int drbg_kcapi_sym_ctr(struct drbg_state *drbg,
  *
  * return: flags
  */
-static inline void drbg_convert_tfm_core(const char *cra_driver_name,
-					 int *coreref, bool *pr)
+void drbg_convert_tfm_core(const char *cra_driver_name, int *coreref, bool *pr)
 {
 	int i = 0;
 	size_t start = 0;
@@ -1902,6 +1905,7 @@ static inline void drbg_convert_tfm_core(const char *cra_driver_name,
 		}
 	}
 }
+EXPORT_SYMBOL(drbg_convert_tfm_core);
 
 static int drbg_kcapi_init(struct crypto_tfm *tfm)
 {
diff --git a/include/crypto/drbg.h b/include/crypto/drbg.h
index 8c9af21efce1..c63b20375235 100644
--- a/include/crypto/drbg.h
+++ b/include/crypto/drbg.h
@@ -282,4 +282,11 @@ enum drbg_prefixes {
 	DRBG_PREFIX3
 };
 
+extern int drbg_alloc_state(struct drbg_state *drbg);
+extern void drbg_dealloc_state(struct drbg_state *drbg);
+extern void drbg_convert_tfm_core(const char *cra_driver_name, int *coreref,
+				  bool *pr);
+extern const struct drbg_core drbg_cores[];
+extern unsigned short drbg_sec_strength(drbg_flag_t flags);
+
 #endif /* _DRBG_H */
-- 
2.23.0





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v24 06/12] LRNG - add SP800-90A DRBG extension
  2019-11-11 18:17 [PATCH v24 00/12] /dev/random - a new approach with full SP800-90B compliance Stephan Müller
                   ` (4 preceding siblings ...)
  2019-11-11 18:21 ` [PATCH v24 05/12] crypto: DRBG - externalize DRBG functions for LRNG Stephan Müller
@ 2019-11-11 18:21 ` Stephan Müller
  2019-11-11 18:22 ` [PATCH v24 07/12] LRNG - add kernel crypto API PRNG extension Stephan Müller
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-11 18:21 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

Using the LRNG switchable DRNG support, the SP800-90A DRBG extension is
implemented.

The DRBG uses the kernel crypto API DRBG implementation. In addition, it
uses the kernel crypto API SHASH support to provide the hashing
operation.

The DRBG supports the choice of either a CTR DRBG using AES-256, HMAC
DRBG with SHA-512 core or Hash DRBG with SHA-512 core. The used core can
be selected with the module parameter lrng_drbg_type. The default is the
CTR DRBG.

When compiling the DRBG extension statically, the DRBG is loaded at
late_initcall stage which implies that with the start of user space, the
user space interfaces of getrandom(2), /dev/random and /dev/urandom
provide random data produced by an SP800-90A DRBG.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Kconfig     |  11 ++
 drivers/char/lrng/Makefile    |   1 +
 drivers/char/lrng/lrng_drbg.c | 274 ++++++++++++++++++++++++++++++++++
 3 files changed, 286 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_drbg.c

diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
index a468d8292bac..bf61e730e50f 100644
--- a/drivers/char/lrng/Kconfig
+++ b/drivers/char/lrng/Kconfig
@@ -59,4 +59,15 @@ menuconfig LRNG_DRNG_SWITCH
 	  accessible via the external interfaces. With this configuration
 	  option other DRNGs can be selected and loaded at runtime.
 
+if LRNG_DRNG_SWITCH
+config LRNG_DRBG
+	tristate "SP800-90A support for the LRNG"
+	select CRYPTO_DRBG_MENU
+	select CRYPTO_CMAC if CRYPTO_DRBG_CTR
+	help
+	  Enable the SP800-90A DRBG support for the LRNG. Once the
+	  module is loaded, output from /dev/random, /dev/urandom,
+	  getrandom(2), or get_random_bytes is provided by a DRBG.
+endif # LRNG_DRNG_SWITCH
+
 endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index 6bac97638767..e3a704b3466c 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -11,3 +11,4 @@ obj-y				+= lrng_pool.o lrng_aux.o \
 obj-$(CONFIG_NUMA)		+= lrng_numa.o
 obj-$(CONFIG_SYSCTL)		+= lrng_proc.o
 obj-$(CONFIG_LRNG_DRNG_SWITCH)	+= lrng_switch.o
+obj-$(CONFIG_LRNG_DRBG)		+= lrng_drbg.o
diff --git a/drivers/char/lrng/lrng_drbg.c b/drivers/char/lrng/lrng_drbg.c
new file mode 100644
index 000000000000..308d9b3ea334
--- /dev/null
+++ b/drivers/char/lrng/lrng_drbg.c
@@ -0,0 +1,274 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * Backend for the LRNG providing the cryptographic primitives using the
+ * kernel crypto API and its DRBG.
+ *
+ * Copyright (C) 2016 - 2019, Stephan Mueller <smueller@chronox.de>
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <crypto/drbg.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/lrng.h>
+
+/*
+ * Define a DRBG plus a hash / MAC used to extract data from the entropy pool.
+ * For LRNG_HASH_NAME you can use a hash or a MAC (HMAC or CMAC) of your choice
+ * (Note, you should use the suggested selections below -- using SHA-1 or MD5
+ * is not wise). The idea is that the used cipher primitive can be selected to
+ * be the same as used for the DRBG. I.e. the LRNG only uses one cipher
+ * primitive using the same cipher implementation with the options offered in
+ * the following. This means, if the CTR DRBG is selected and AES-NI is present,
+ * both the CTR DRBG and the selected cmac(aes) use AES-NI.
+ *
+ * The security strengths of the DRBGs are all 256 bits according to
+ * SP800-57 section 5.6.1.
+ *
+ * This definition is allowed to be changed.
+ */
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+static unsigned int lrng_drbg_type = 0;
+#elif defined CONFIG_CRYPTO_DRBG_HMAC
+static unsigned int lrng_drbg_type = 1;
+#elif defined CONFIG_CRYPTO_DRBG_HASH
+static unsigned int lrng_drbg_type = 2;
+#else
+#error "Unknown DRBG in use"
+#endif
+
+/* The parameter must be r/o in sysfs as otherwise races appear. */
+module_param(lrng_drbg_type, uint, 0444);
+MODULE_PARM_DESC(lrng_drbg_type, "DRBG type used for LRNG (0->CTR_DRBG, "
+				 "1->HMAC_DRBG, 2->Hash_DRBG)");
+
+struct lrng_drbg {
+	const char *hash_name;
+	const char *drbg_core;
+};
+
+static const struct lrng_drbg lrng_drbg_types[] = {
+	{	/* CTR_DRBG with AES-256 using derivation function */
+		.hash_name = "cmac(aes)",
+		.drbg_core = "drbg_nopr_ctr_aes256",
+	}, {	/* HMAC_DRBG with SHA-512 */
+		.hash_name = "sha512",
+		.drbg_core = "drbg_nopr_hmac_sha512",
+	}, {	/* Hash_DRBG with SHA-512 using derivation function */
+		.hash_name = "sha512",
+		.drbg_core = "drbg_nopr_sha512"
+	}
+};
+
+struct lrng_hash_info {
+	struct shash_desc shash;
+	char ctx[];
+};
+
+static int lrng_drbg_drng_seed_helper(void *drng, const u8 *inbuf, u32 inbuflen)
+{
+	struct drbg_state *drbg = (struct drbg_state *)drng;
+	LIST_HEAD(seedlist);
+	struct drbg_string data;
+	int ret;
+
+	drbg_string_fill(&data, inbuf, inbuflen);
+	list_add_tail(&data.list, &seedlist);
+	ret = drbg->d_ops->update(drbg, &seedlist, drbg->seeded);
+
+	if (ret >= 0)
+		drbg->seeded = true;
+
+	return ret;
+}
+
+static int lrng_drbg_drng_generate_helper(void *drng, u8 *outbuf, u32 outbuflen)
+{
+	struct drbg_state *drbg = (struct drbg_state *)drng;
+
+	return drbg->d_ops->generate(drbg, outbuf, outbuflen, NULL);
+}
+
+static void *lrng_drbg_drng_alloc(u32 sec_strength)
+{
+	struct drbg_state *drbg;
+	int coreref = -1;
+	bool pr = false;
+	int ret;
+
+	drbg_convert_tfm_core(lrng_drbg_types[lrng_drbg_type].drbg_core,
+			      &coreref, &pr);
+	if (coreref < 0)
+		return ERR_PTR(-EFAULT);
+
+	drbg = kzalloc(sizeof(struct drbg_state), GFP_KERNEL);
+	if (!drbg)
+		return ERR_PTR(-ENOMEM);
+
+	drbg->core = &drbg_cores[coreref];
+	drbg->seeded = false;
+	ret = drbg_alloc_state(drbg);
+	if (ret)
+		goto err;
+
+	if (sec_strength > drbg_sec_strength(drbg->core->flags)) {
+		pr_err("Security strength of DRBG (%u bits) lower than "
+		       "requested by LRNG (%u bits)\n",
+			drbg_sec_strength(drbg->core->flags) * 8,
+			sec_strength * 8);
+		goto dealloc;
+	}
+
+	if (sec_strength < drbg_sec_strength(drbg->core->flags))
+		pr_warn("Security strength of DRBG (%u bits) higher than "
+			"requested by LRNG (%u bits)\n",
+			drbg_sec_strength(drbg->core->flags) * 8,
+			sec_strength * 8);
+
+	pr_info("DRBG with %s core allocated\n", drbg->core->backend_cra_name);
+
+	return drbg;
+
+dealloc:
+	if (drbg->d_ops)
+		drbg->d_ops->crypto_fini(drbg);
+	drbg_dealloc_state(drbg);
+err:
+	kfree(drbg);
+	return ERR_PTR(-EINVAL);
+}
+
+static void lrng_drbg_drng_dealloc(void *drng)
+{
+	struct drbg_state *drbg = (struct drbg_state *)drng;
+
+	drbg_dealloc_state(drbg);
+	kzfree(drbg);
+	pr_info("DRBG deallocated\n");
+}
+
+static void *lrng_drbg_hash_alloc(const u8 *key, u32 keylen)
+{
+	struct lrng_hash_info *lrng_hash;
+	struct crypto_shash *tfm;
+	int size, ret;
+
+	tfm = crypto_alloc_shash(lrng_drbg_types[lrng_drbg_type].hash_name,
+				 0, 0);
+	if (IS_ERR(tfm)) {
+		pr_err("could not allocate hash %s\n",
+		       lrng_drbg_types[lrng_drbg_type].hash_name);
+		return ERR_CAST(tfm);
+	}
+
+	size = sizeof(struct lrng_hash_info) + crypto_shash_descsize(tfm);
+	lrng_hash = kmalloc(size, GFP_KERNEL);
+	if (!lrng_hash) {
+		crypto_free_shash(tfm);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	lrng_hash->shash.tfm = tfm;
+
+	/* If the used hash is no MAC, ignore the ENOSYS return code */
+	ret = crypto_shash_setkey(tfm, key, keylen);
+	if (ret && ret != -ENOSYS) {
+		pr_err("could not set the key for MAC\n");
+		crypto_free_shash(tfm);
+		kfree(lrng_hash);
+		return ERR_PTR(ret);
+	}
+
+	pr_info("Hash %s allocated\n",
+		lrng_drbg_types[lrng_drbg_type].hash_name);
+
+	return lrng_hash;
+}
+
+static void lrng_drbg_hash_dealloc(void *hash)
+{
+	struct lrng_hash_info *lrng_hash = (struct lrng_hash_info *)hash;
+	struct shash_desc *shash = &lrng_hash->shash;
+	struct crypto_shash *tfm = shash->tfm;
+
+	crypto_free_shash(tfm);
+	kfree(lrng_hash);
+	pr_info("Hash deallocated\n");
+}
+
+static u32 lrng_drbg_hash_digestsize(void *hash)
+{
+	struct lrng_hash_info *lrng_hash = (struct lrng_hash_info *)hash;
+	struct shash_desc *shash = &lrng_hash->shash;
+
+	return crypto_shash_digestsize(shash->tfm);
+}
+
+static int lrng_drbg_hash_buffer(void *hash, const u8 *inbuf, u32 inbuflen,
+				 u8 *digest)
+{
+	struct lrng_hash_info *lrng_hash = (struct lrng_hash_info *)hash;
+	struct shash_desc *shash = &lrng_hash->shash;
+
+	return crypto_shash_digest(shash, inbuf, inbuflen, digest);
+}
+
+static const char *lrng_drbg_name(void)
+{
+	return lrng_drbg_types[lrng_drbg_type].drbg_core;
+}
+
+static const char *lrng_hash_name(void)
+{
+	return lrng_drbg_types[lrng_drbg_type].hash_name;
+}
+
+const static struct lrng_crypto_cb lrng_drbg_crypto_cb = {
+	.lrng_drng_name			= lrng_drbg_name,
+	.lrng_hash_name			= lrng_hash_name,
+	.lrng_drng_alloc		= lrng_drbg_drng_alloc,
+	.lrng_drng_dealloc		= lrng_drbg_drng_dealloc,
+	.lrng_drng_seed_helper		= lrng_drbg_drng_seed_helper,
+	.lrng_drng_generate_helper	= lrng_drbg_drng_generate_helper,
+	.lrng_drng_generate_helper_full	= lrng_drbg_drng_generate_helper,
+	.lrng_hash_alloc		= lrng_drbg_hash_alloc,
+	.lrng_hash_dealloc		= lrng_drbg_hash_dealloc,
+	.lrng_hash_digestsize		= lrng_drbg_hash_digestsize,
+	.lrng_hash_buffer		= lrng_drbg_hash_buffer,
+};
+
+static int __init lrng_drbg_init(void)
+{
+	if (lrng_drbg_type >= ARRAY_SIZE(lrng_drbg_types)) {
+		pr_err("lrng_drbg_type parameter too large (given %u - max: %lu)",
+		       lrng_drbg_type,
+		       (unsigned long)ARRAY_SIZE(lrng_drbg_types) - 1);
+		return -EAGAIN;
+	}
+	return lrng_set_drng_cb(&lrng_drbg_crypto_cb);
+}
+
+static void __exit lrng_drbg_exit(void)
+{
+	lrng_set_drng_cb(NULL);
+}
+
+late_initcall(lrng_drbg_init);
+module_exit(lrng_drbg_exit);
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
+MODULE_DESCRIPTION("Linux Random Number Generator - SP800-90A DRBG backend");
-- 
2.23.0





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v24 07/12] LRNG - add kernel crypto API PRNG extension
  2019-11-11 18:17 [PATCH v24 00/12] /dev/random - a new approach with full SP800-90B compliance Stephan Müller
                   ` (5 preceding siblings ...)
  2019-11-11 18:21 ` [PATCH v24 06/12] LRNG - add SP800-90A DRBG extension Stephan Müller
@ 2019-11-11 18:22 ` Stephan Müller
  2019-11-11 18:23 ` [PATCH v24 08/12] crypto: provide access to a static Jitter RNG state Stephan Müller
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-11 18:22 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

Add runtime-pluggable support for all PRNGs that are accessible via
the kernel crypto API, including hardware PRNGs. The PRNG is selected
with the module parameter drng_name where the name must be one that the
kernel crypto API can resolve into an RNG.

This allows using of the kernel crypto API PRNG implementations that
provide an interface to hardware PRNGs. Using this extension,
the LRNG uses the hardware PRNGs to generate random numbers. An
example is the S390 CPACF support providing such a PRNG.

The hash is provided by a kernel crypto API SHASH whose digest size
complies with the seedsize of the PRNG.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Kconfig      |  10 +
 drivers/char/lrng/Makefile     |   1 +
 drivers/char/lrng/lrng_kcapi.c | 341 +++++++++++++++++++++++++++++++++
 3 files changed, 352 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_kcapi.c

diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
index bf61e730e50f..eb1cd63433dc 100644
--- a/drivers/char/lrng/Kconfig
+++ b/drivers/char/lrng/Kconfig
@@ -68,6 +68,16 @@ config LRNG_DRBG
 	  Enable the SP800-90A DRBG support for the LRNG. Once the
 	  module is loaded, output from /dev/random, /dev/urandom,
 	  getrandom(2), or get_random_bytes is provided by a DRBG.
+
+config LRNG_KCAPI
+	tristate "Kernel Crypto API support for the LRNG"
+	select CRYPTO_RNG
+	help
+	  Enable the support for generic pseudo-random number
+	  generators offered by the kernel crypto API with the
+	  LRNG. Once the module is loaded, output from /dev/random,
+	  /dev/urandom, getrandom(2), or get_random_bytes is
+	  provided by the selected kernel crypto API RNG.
 endif # LRNG_DRNG_SWITCH
 
 endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index e3a704b3466c..027b6ea51c20 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -12,3 +12,4 @@ obj-$(CONFIG_NUMA)		+= lrng_numa.o
 obj-$(CONFIG_SYSCTL)		+= lrng_proc.o
 obj-$(CONFIG_LRNG_DRNG_SWITCH)	+= lrng_switch.o
 obj-$(CONFIG_LRNG_DRBG)		+= lrng_drbg.o
+obj-$(CONFIG_LRNG_KCAPI)	+= lrng_kcapi.o
diff --git a/drivers/char/lrng/lrng_kcapi.c b/drivers/char/lrng/lrng_kcapi.c
new file mode 100644
index 000000000000..a7ee990c4674
--- /dev/null
+++ b/drivers/char/lrng/lrng_kcapi.c
@@ -0,0 +1,341 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * Backend for the LRNG providing the cryptographic primitives using the
+ * kernel crypto API.
+ *
+ * Copyright (C) 2018 - 2019, Stephan Mueller <smueller@chronox.de>
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <crypto/hash.h>
+#include <crypto/rng.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/lrng.h>
+
+static char *drng_name = NULL;
+module_param(drng_name, charp, 0444);
+MODULE_PARM_DESC(drng_name, "Kernel crypto API name of DRNG");
+
+static char *pool_hash = "sha512";
+module_param(pool_hash, charp, 0444);
+MODULE_PARM_DESC(pool_hash,
+		 "Kernel crypto API name of hash or keyed message digest to read the entropy pool");
+
+static char *seed_hash = NULL;
+module_param(seed_hash, charp, 0444);
+MODULE_PARM_DESC(seed_hash,
+		 "Kernel crypto API name of hash with output size equal to seedsize of DRNG to bring seed string to the size required by the DRNG");
+
+struct lrng_hash_info {
+	struct shash_desc shash;
+	char ctx[];
+};
+
+struct lrng_drng_info {
+	struct crypto_rng *kcapi_rng;
+	struct lrng_hash_info *lrng_hash;
+};
+
+static struct lrng_hash_info *_lrng_kcapi_hash_alloc(const char *name)
+{
+	struct lrng_hash_info *lrng_hash;
+	struct crypto_shash *tfm;
+	int size;
+
+	if (!name) {
+		pr_err("Hash name missing\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	tfm = crypto_alloc_shash(name, 0, 0);
+	if (IS_ERR(tfm)) {
+		pr_err("could not allocate hash %s\n", name);
+		return ERR_CAST(tfm);
+	}
+
+	size = sizeof(struct lrng_hash_info) + crypto_shash_descsize(tfm);
+	lrng_hash = kmalloc(size, GFP_KERNEL);
+	if (!lrng_hash) {
+		crypto_free_shash(tfm);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	lrng_hash->shash.tfm = tfm;
+
+	return lrng_hash;
+}
+
+static inline u32 _lrng_kcapi_hash_digestsize(struct lrng_hash_info *lrng_hash)
+{
+	struct shash_desc *shash = &lrng_hash->shash;
+	struct crypto_shash *tfm = shash->tfm;
+
+	return crypto_shash_digestsize(tfm);
+}
+
+static inline void _lrng_kcapi_hash_free(struct lrng_hash_info *lrng_hash)
+{
+	struct shash_desc *shash = &lrng_hash->shash;
+	struct crypto_shash *tfm = shash->tfm;
+
+	crypto_free_shash(tfm);
+	kfree(lrng_hash);
+}
+
+static void *lrng_kcapi_hash_alloc(const u8 *key, u32 keylen)
+{
+	struct lrng_hash_info *lrng_hash;
+	int ret;
+
+	lrng_hash = _lrng_kcapi_hash_alloc(pool_hash);
+	if (IS_ERR(lrng_hash))
+		return ERR_CAST(lrng_hash);
+
+	/* If the used hash is no MAC, ignore the ENOSYS return code */
+	ret = crypto_shash_setkey(lrng_hash->shash.tfm, key, keylen);
+	if (ret && ret != -ENOSYS) {
+		pr_err("could not set the key for MAC\n");
+		_lrng_kcapi_hash_free(lrng_hash);
+		return ERR_PTR(ret);
+	}
+
+	pr_info("Hash %s allocated\n", pool_hash);
+
+	return lrng_hash;
+}
+
+static void lrng_kcapi_hash_dealloc(void *hash)
+{
+	struct lrng_hash_info *lrng_hash = (struct lrng_hash_info *)hash;
+
+	_lrng_kcapi_hash_free(lrng_hash);
+	pr_info("Hash %s deallocated\n", pool_hash);
+}
+
+static u32 lrng_kcapi_hash_digestsize(void *hash)
+{
+	struct lrng_hash_info *lrng_hash = (struct lrng_hash_info *)hash;
+
+	return _lrng_kcapi_hash_digestsize(lrng_hash);
+}
+
+static int lrng_kcapi_hash_buffer(void *hash, const u8 *inbuf, u32 inbuflen,
+				  u8 *digest)
+{
+	struct lrng_hash_info *lrng_hash = (struct lrng_hash_info *)hash;
+	struct shash_desc *shash = &lrng_hash->shash;
+
+	return crypto_shash_digest(shash, inbuf, inbuflen, digest);
+}
+
+static int lrng_kcapi_drng_seed_helper(void *drng, const u8 *inbuf,
+				       u32 inbuflen)
+{
+	struct lrng_drng_info *lrng_drng_info = (struct lrng_drng_info *)drng;
+	struct crypto_rng *kcapi_rng = lrng_drng_info->kcapi_rng;
+	struct lrng_hash_info *lrng_hash = lrng_drng_info->lrng_hash;
+
+	if (lrng_hash) {
+		struct shash_desc *shash = &lrng_hash->shash;
+		u32 digestsize = _lrng_kcapi_hash_digestsize(lrng_hash);
+		u8 digest[64] __aligned(8);
+		int ret;
+
+		BUG_ON(digestsize > sizeof(digest));
+
+		ret = crypto_shash_digest(shash, inbuf, inbuflen, digest);
+		if (ret)
+			return ret;
+
+		ret = crypto_rng_reset(kcapi_rng, digest, digestsize);
+		if (ret)
+			return ret;
+
+		memzero_explicit(digest, digestsize);
+
+		return 0;
+	} else {
+		return crypto_rng_reset(kcapi_rng, inbuf, inbuflen);
+	}
+}
+
+static int lrng_kcapi_drng_generate_helper(void *drng, u8 *outbuf,
+					   u32 outbuflen)
+{
+	struct lrng_drng_info *lrng_drng_info = (struct lrng_drng_info *)drng;
+	struct crypto_rng *kcapi_rng = lrng_drng_info->kcapi_rng;
+	int ret = crypto_rng_get_bytes(kcapi_rng, outbuf, outbuflen);
+
+	if (ret < 0)
+		return ret;
+
+	return outbuflen;
+}
+
+static void *lrng_kcapi_drng_alloc(u32 sec_strength)
+{
+	struct lrng_drng_info *lrng_drng_info;
+	struct crypto_rng *kcapi_rng;
+	int seedsize;
+	void *ret =  ERR_PTR(-ENOMEM);
+
+	if (!drng_name) {
+		pr_err("DRNG name missing\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (!memcmp(drng_name, "drbg", 4)) {
+		pr_err("SP800-90A DRBG cannot be allocated using lrng_kcapi "
+		       "backend, use lrng_drbg backend instead\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (!memcmp(drng_name, "stdrng", 6)) {
+		pr_err("stdrng cannot be allocated using lrng_kcapi backend, "
+		       "it is too unspecific and potentially may allocate the "
+		       "DRBG\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	lrng_drng_info = kmalloc(sizeof(*lrng_drng_info), GFP_KERNEL);
+	if (!lrng_drng_info)
+		return ERR_PTR(-ENOMEM);
+
+	kcapi_rng = crypto_alloc_rng(drng_name, 0, 0);
+	if (IS_ERR(kcapi_rng)) {
+		pr_err("DRNG %s cannot be allocated\n", drng_name);
+		ret = ERR_CAST(kcapi_rng);
+		goto free;
+	}
+	lrng_drng_info->kcapi_rng = kcapi_rng;
+
+	seedsize =  crypto_rng_seedsize(kcapi_rng);
+
+	if (sec_strength > seedsize)
+		pr_info("Seedsize DRNG (%u bits) lower than "
+			"security strength of LRNG noise source (%u bits)\n",
+			crypto_rng_seedsize(kcapi_rng) * 8,
+			sec_strength * 8);
+
+	if (seedsize) {
+		struct lrng_hash_info *lrng_hash;
+
+		if (!seed_hash) {
+			switch (seedsize) {
+			case 32:
+				seed_hash = "sha256";
+				break;
+			case 48:
+				seed_hash = "sha384";
+				break;
+			case 64:
+				seed_hash = "sha512";
+				break;
+			default:
+				pr_err("Seed size %d cannot be processed\n",
+				       seedsize);
+				goto dealloc;
+				break;
+			}
+		}
+
+		lrng_hash = _lrng_kcapi_hash_alloc(seed_hash);
+		if (IS_ERR(lrng_hash)) {
+			ret = ERR_CAST(lrng_hash);
+			goto dealloc;
+		}
+
+		if (seedsize != _lrng_kcapi_hash_digestsize(lrng_hash)) {
+			pr_err("Seed hash output size not equal to DRNG seed "
+			       "size\n");
+			_lrng_kcapi_hash_free(lrng_hash);
+			ret = ERR_PTR(-EINVAL);
+			goto dealloc;
+		}
+
+		lrng_drng_info->lrng_hash = lrng_hash;
+
+		pr_info("Seed hash %s allocated\n", seed_hash);
+	} else {
+		lrng_drng_info->lrng_hash = NULL;
+	}
+
+	pr_info("Kernel crypto API DRNG %s allocated\n", drng_name);
+
+	return lrng_drng_info;
+
+dealloc:
+	crypto_free_rng(kcapi_rng);
+free:
+	kfree(lrng_drng_info);
+	return ret;
+}
+
+static void lrng_kcapi_drng_dealloc(void *drng)
+{
+	struct lrng_drng_info *lrng_drng_info = (struct lrng_drng_info *)drng;
+	struct crypto_rng *kcapi_rng = lrng_drng_info->kcapi_rng;
+	struct lrng_hash_info *lrng_hash = lrng_drng_info->lrng_hash;
+
+	crypto_free_rng(kcapi_rng);
+	if (lrng_hash) {
+		_lrng_kcapi_hash_free(lrng_hash);
+		pr_info("Seed hash %s deallocated\n", seed_hash);
+	}
+	kfree(lrng_drng_info);
+	pr_info("DRNG %s deallocated\n", drng_name);
+}
+
+static const char *lrng_kcapi_drng_name(void)
+{
+	return drng_name;
+}
+
+static const char *lrng_kcapi_pool_hash(void)
+{
+	return pool_hash;
+}
+
+const static struct lrng_crypto_cb lrng_kcapi_crypto_cb = {
+	.lrng_drng_name			= lrng_kcapi_drng_name,
+	.lrng_hash_name			= lrng_kcapi_pool_hash,
+	.lrng_drng_alloc		= lrng_kcapi_drng_alloc,
+	.lrng_drng_dealloc		= lrng_kcapi_drng_dealloc,
+	.lrng_drng_seed_helper		= lrng_kcapi_drng_seed_helper,
+	.lrng_drng_generate_helper	= lrng_kcapi_drng_generate_helper,
+	.lrng_drng_generate_helper_full	= lrng_kcapi_drng_generate_helper,
+	.lrng_hash_alloc		= lrng_kcapi_hash_alloc,
+	.lrng_hash_dealloc		= lrng_kcapi_hash_dealloc,
+	.lrng_hash_digestsize		= lrng_kcapi_hash_digestsize,
+	.lrng_hash_buffer		= lrng_kcapi_hash_buffer,
+};
+
+static int __init lrng_kcapi_init(void)
+{
+	return lrng_set_drng_cb(&lrng_kcapi_crypto_cb);
+}
+static void __exit lrng_kcapi_exit(void)
+{
+	lrng_set_drng_cb(NULL);
+}
+
+late_initcall(lrng_kcapi_init);
+module_exit(lrng_kcapi_exit);
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
+MODULE_DESCRIPTION("Linux Random Number Generator - kernel crypto API DRNG backend");
-- 
2.23.0





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v24 08/12] crypto: provide access to a static Jitter RNG state
  2019-11-11 18:17 [PATCH v24 00/12] /dev/random - a new approach with full SP800-90B compliance Stephan Müller
                   ` (6 preceding siblings ...)
  2019-11-11 18:22 ` [PATCH v24 07/12] LRNG - add kernel crypto API PRNG extension Stephan Müller
@ 2019-11-11 18:23 ` Stephan Müller
  2019-11-11 18:23 ` [PATCH v24 09/12] LRNG - add Jitter RNG fast noise source Stephan Müller
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-11 18:23 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

To support the LRNG operation which uses the Jitter RNG separately
from the kernel crypto API, at a time where potentially the regular
memory management is not yet initialized, the Jitter RNG needs to
provide a state whose memory is defined at compile time. As only once
instance will ever be needed by the LRNG, define once static memory
block which is solely to be used by the LRNG.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 crypto/jitterentropy.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/crypto/jitterentropy.c b/crypto/jitterentropy.c
index 77fa2120fe0c..3a815495f778 100644
--- a/crypto/jitterentropy.c
+++ b/crypto/jitterentropy.c
@@ -644,3 +644,26 @@ int jent_entropy_init(void)
 
 	return 0;
 }
+
+struct rand_data *jent_lrng_entropy_collector(void)
+{
+	static unsigned char lrng_jent_mem[JENT_MEMORY_SIZE];
+	static struct rand_data lrng_jent_state = {
+		.data		= 0,
+		.old_data	= 0,
+		.prev_time	= 0,
+		.last_delta	= 0,
+		.last_delta2	= 0,
+		.osr		= 1,
+		.mem		= lrng_jent_mem,
+		.memlocation	= 0,
+		.memblocks	= JENT_MEMORY_BLOCKSIZE,
+		.memblocksize	= JENT_MEMORY_BLOCKS,
+		.memaccessloops	= JENT_MEMORY_ACCESSLOOPS,
+	};
+
+	if (jent_entropy_init())
+		return NULL;
+
+	return &lrng_jent_state;
+}
-- 
2.23.0





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v24 09/12] LRNG - add Jitter RNG fast noise source
  2019-11-11 18:17 [PATCH v24 00/12] /dev/random - a new approach with full SP800-90B compliance Stephan Müller
                   ` (7 preceding siblings ...)
  2019-11-11 18:23 ` [PATCH v24 08/12] crypto: provide access to a static Jitter RNG state Stephan Müller
@ 2019-11-11 18:23 ` Stephan Müller
  2019-11-11 18:24 ` [PATCH v24 10/12] LRNG - add TRNG support Stephan Müller
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-11 18:23 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

The Jitter RNG fast noise source implemented as part of the kernel
crypto API is queried for 256 bits of entropy at the time the seed
buffer managed by the LRNG is about to be filled.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Kconfig     |  11 ++++
 drivers/char/lrng/Makefile    |   1 +
 drivers/char/lrng/lrng_jent.c | 101 ++++++++++++++++++++++++++++++++++
 3 files changed, 113 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_jent.c

diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
index eb1cd63433dc..c6d26b88cdac 100644
--- a/drivers/char/lrng/Kconfig
+++ b/drivers/char/lrng/Kconfig
@@ -80,4 +80,15 @@ config LRNG_KCAPI
 	  provided by the selected kernel crypto API RNG.
 endif # LRNG_DRNG_SWITCH
 
+config LRNG_JENT
+	bool "Enable Jitter RNG as LRNG Seed Source"
+	select CRYPTO_JITTERENTROPY
+	help
+	  The Linux RNG may use the Jitter RNG as noise source. Enabling
+	  this option enables the use of the Jitter RNG. Its default
+	  entropy level is 16 bits of entropy per 256 data bits delivered
+	  by the Jitter RNG. This entropy level can be changed at boot
+	  time or at runtime with the lrng_base.jitterrng configuration
+	  variable.
+
 endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index 027b6ea51c20..a87d800c9aae 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -13,3 +13,4 @@ obj-$(CONFIG_SYSCTL)		+= lrng_proc.o
 obj-$(CONFIG_LRNG_DRNG_SWITCH)	+= lrng_switch.o
 obj-$(CONFIG_LRNG_DRBG)		+= lrng_drbg.o
 obj-$(CONFIG_LRNG_KCAPI)	+= lrng_kcapi.o
+obj-$(CONFIG_LRNG_JENT)		+= lrng_jent.o
diff --git a/drivers/char/lrng/lrng_jent.c b/drivers/char/lrng/lrng_jent.c
new file mode 100644
index 000000000000..ce45f6be9faf
--- /dev/null
+++ b/drivers/char/lrng/lrng_jent.c
@@ -0,0 +1,101 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG Fast Noise Source: Jitter RNG
+ *
+ * Copyright (C) 2016 - 2019, Stephan Mueller <smueller@chronox.de>
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "lrng_internal.h"
+
+/*
+ * Estimated entropy of data is a 16th of LRNG_DRNG_SECURITY_STRENGTH_BITS.
+ * Albeit a full entropy assessment is provided for the noise source indicating
+ * that it provides high entropy rates and considering that it deactivates
+ * when it detects insufficient hardware, the chosen under estimation of
+ * entropy is considered to be acceptable to all reviewers.
+ */
+static u32 jitterrng = LRNG_DRNG_SECURITY_STRENGTH_BITS>>4;
+module_param(jitterrng, uint, 0644);
+MODULE_PARM_DESC(jitterrng, "Entropy in bits of 256 data bits from Jitter "
+			    "RNG noise source");
+
+/**
+ * Get Jitter RNG entropy
+ *
+ * @outbuf buffer to store entropy
+ * @outbuflen length of buffer
+ * @return > 0 on success where value provides the added entropy in bits
+ *	   0 if no fast source was available
+ */
+struct rand_data;
+struct rand_data *jent_lrng_entropy_collector(void);
+int jent_read_entropy(struct rand_data *ec, unsigned char *data,
+		      unsigned int len);
+static struct rand_data *lrng_jent_state;
+
+u32 lrng_get_jent(u8 *outbuf, unsigned int outbuflen)
+{
+	int ret;
+	u32 ent_bits = jitterrng;
+	unsigned long flags;
+	static DEFINE_SPINLOCK(lrng_jent_lock);
+	static int lrng_jent_initialized = 0;
+
+	spin_lock_irqsave(&lrng_jent_lock, flags);
+
+	if (!ent_bits || (lrng_jent_initialized == -1)) {
+		spin_unlock_irqrestore(&lrng_jent_lock, flags);
+		return 0;
+	}
+
+	if (!lrng_jent_initialized) {
+		lrng_jent_state = jent_lrng_entropy_collector();
+		if (!lrng_jent_state) {
+			jitterrng = 0;
+			lrng_jent_initialized = -1;
+			spin_unlock_irqrestore(&lrng_jent_lock, flags);
+			pr_info("Jitter RNG unusable on current system\n");
+			return 0;
+		}
+		lrng_jent_initialized = 1;
+		pr_debug("Jitter RNG working on current system\n");
+	}
+	ret = jent_read_entropy(lrng_jent_state, outbuf, outbuflen);
+	spin_unlock_irqrestore(&lrng_jent_lock, flags);
+
+	if (ret) {
+		pr_debug("Jitter RNG failed with %d\n", ret);
+		return 0;
+	}
+
+	/* Obtain entropy statement */
+	if (outbuflen != LRNG_DRNG_SECURITY_STRENGTH_BYTES)
+		ent_bits = (ent_bits * outbuflen<<3) /
+			   LRNG_DRNG_SECURITY_STRENGTH_BITS;
+	/* Cap entropy to buffer size in bits */
+	ent_bits = min_t(u32, ent_bits, outbuflen<<3);
+	pr_debug("obtained %u bits of entropy from Jitter RNG noise source\n",
+		 ent_bits);
+
+	return ent_bits;
+}
+
+u32 lrng_jent_entropylevel(void)
+{
+	return min_t(u32, jitterrng, LRNG_DRNG_SECURITY_STRENGTH_BITS);
+}
-- 
2.23.0





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v24 10/12] LRNG - add TRNG support
  2019-11-11 18:17 [PATCH v24 00/12] /dev/random - a new approach with full SP800-90B compliance Stephan Müller
                   ` (8 preceding siblings ...)
  2019-11-11 18:23 ` [PATCH v24 09/12] LRNG - add Jitter RNG fast noise source Stephan Müller
@ 2019-11-11 18:24 ` Stephan Müller
  2019-11-11 18:26 ` [PATCH v24 11/12] LRNG - add SP800-90B compliant health tests Stephan Müller
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-11 18:24 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

The True Random Number Generator (TRNG) provides a random number
generator with prediction resistance (SP800-90A terminology) or an NTG.1
(AIS 31 terminology).

When enabled, it obtains random numbers from the entropy pool and
maintains the information with how much entropy it was seeded with. The
TRNG only generates as much output data as it has as entropy.

The secondary DRNGs seed from the TRNG if it is present. In addition,
the /dev/random device accesses the TRNG.

If the TRNG is disabled, the secondary DRNGs seed from the entropy pool
and /dev/random behaves like getrandom(2).

The TRNG benefits from the switchable DRNG support which implies that
data provided via /dev/random is generated by the loaded DRNG.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Kconfig     |  22 +++
 drivers/char/lrng/Makefile    |   1 +
 drivers/char/lrng/lrng_trng.c | 301 ++++++++++++++++++++++++++++++++++
 3 files changed, 324 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_trng.c

diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
index c6d26b88cdac..efc5f9aaa2a3 100644
--- a/drivers/char/lrng/Kconfig
+++ b/drivers/char/lrng/Kconfig
@@ -91,4 +91,26 @@ config LRNG_JENT
 	  time or at runtime with the lrng_base.jitterrng configuration
 	  variable.
 
+config LRNG_TRNG_SUPPORT
+	bool "Enable True Random Number Generator support"
+	default y
+	help
+	  The true random number generator (TRNG) support, also
+	  known as DRNG with prediction resistance (SP800-90A
+	  terminology) or NTG.1 (AIS 31 terminology), generates
+	  random numbers after a successful reseed with entropy.
+	  Only when new entropy is provided for a new generation
+	  request, random data is provided with an equal amount
+	  as entropy was added. The TRNG is available via
+	  /dev/random.
+
+	  If the support is not enabled, /dev/random ensures that
+	  it received sufficient initial entropy and will produce
+	  random data without requiring a constant reseed with
+	  entropy. Yet it tries to regularly reseed itself with
+	  fresh entropy.
+
+	  With the TRNG support the /dev/random device will block
+	  if insufficient entropy is available.
+
 endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index a87d800c9aae..1c72bc060bce 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -14,3 +14,4 @@ obj-$(CONFIG_LRNG_DRNG_SWITCH)	+= lrng_switch.o
 obj-$(CONFIG_LRNG_DRBG)		+= lrng_drbg.o
 obj-$(CONFIG_LRNG_KCAPI)	+= lrng_kcapi.o
 obj-$(CONFIG_LRNG_JENT)		+= lrng_jent.o
+obj-$(CONFIG_LRNG_TRNG_SUPPORT)	+= lrng_trng.o
diff --git a/drivers/char/lrng/lrng_trng.c b/drivers/char/lrng/lrng_trng.c
new file mode 100644
index 000000000000..ffd922192841
--- /dev/null
+++ b/drivers/char/lrng/lrng_trng.c
@@ -0,0 +1,301 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG True Random Number Generator (TRNG) processing
+ *
+ * Copyright (C) 2016 - 2019, Stephan Mueller <smueller@chronox.de>
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/lrng.h>
+
+#include "lrng_internal.h"
+
+/* TRNG state handle */
+struct lrng_trng {
+	void *trng;				/* TRNG handle */
+	void *hash;				/* Hash handle */
+	u32 trng_entropy_bits;			/* TRNG entropy level */
+	const struct lrng_crypto_cb *crypto_cb;	/* Crypto callbacks */
+	struct mutex lock;
+};
+
+/* TRNG for /dev/random and seed source for the secondary DRNG(s) */
+static struct lrng_trng lrng_trng = {
+	.trng		= &primary_chacha20,
+	.crypto_cb	= &lrng_cc20_crypto_cb,
+	.lock		= __MUTEX_INITIALIZER(lrng_trng.lock)
+};
+
+/********************************** Helper ************************************/
+
+void lrng_trng_reset(void)
+{
+	lrng_trng.trng_entropy_bits = 0;
+	pr_debug("reset TRNG\n");
+}
+
+void lrng_trng_init(void)
+{
+	mutex_lock(&lrng_trng.lock);
+	lrng_trng_reset();
+	lrng_cc20_init_state(&primary_chacha20);
+	mutex_unlock(&lrng_trng.lock);
+}
+
+/************************* Random Number Generation ***************************/
+
+/* Caller must hold lrng_trng.lock */
+static int lrng_trng_generate(u8 *outbuf, u32 outbuflen, bool fullentropy)
+{
+	struct lrng_trng *trng = &lrng_trng;
+	const struct lrng_crypto_cb *crypto_cb = trng->crypto_cb;
+	int ret;
+
+	/* /dev/random only works from a fully seeded DRNG */
+	if (fullentropy && !lrng_state_operational())
+		return 0;
+
+	/*
+	 * Only deliver as many bytes as the DRNG is seeded with except during
+	 * initialization to provide a first seed to the secondary DRNG.
+	 */
+	if (lrng_state_min_seeded())
+		outbuflen = min_t(u32, outbuflen, trng->trng_entropy_bits>>3);
+	else
+		outbuflen = min_t(u32, outbuflen,
+				  LRNG_MIN_SEED_ENTROPY_BITS>>3);
+	if (!outbuflen)
+		return 0;
+
+	ret = crypto_cb->lrng_drng_generate_helper_full(trng->trng, outbuf,
+							outbuflen);
+	if (ret != outbuflen) {
+		pr_warn("getting random data from TRNG failed (%d)\n",
+			ret);
+		return ret;
+	}
+
+	if (trng->trng_entropy_bits > (u32)(ret<<3))
+		trng->trng_entropy_bits -= ret<<3;
+	else
+		trng->trng_entropy_bits = 0;
+	pr_debug("obtained %d bytes of random data from TRNG\n", ret);
+	pr_debug("TRNG entropy level at %u bits\n",
+		 trng->trng_entropy_bits);
+
+	return ret;
+}
+
+/**
+ * Inject data into the TRNG with a given entropy value. The function calls
+ * the DRNG's update function. This function also generates random data if
+ * requested by caller. The caller is only returned the amount of random data
+ * that is at most equal to the amount of entropy that just seeded the DRNG.
+ *
+ * Note, this function seeds the TRNG and generates data in an atomic operation.
+ *
+ * @inbuf: buffer to inject
+ * @inbuflen: length of inbuf
+ * @entropy_bits: entropy value of the data in inbuf in bits
+ * @outbuf: buffer to fill immediately after seeding to get full entropy
+ * @outbuflen: length of outbuf
+ * @fullentropy: start /dev/random output only after the DRNG was fully seeded
+ * @return: number of bytes written to outbuf, 0 if outbuf is not supplied,
+ *	    or < 0 in case of error
+ */
+static int lrng_trng_inject(const u8 *inbuf, u32 inbuflen, u32 entropy_bits,
+			    u8 *outbuf, u32 outbuflen, bool fullentropy)
+{
+	struct lrng_trng *trng = &lrng_trng;
+	int ret;
+
+	/* cap the maximum entropy value to the provided data length */
+	entropy_bits = min_t(u32, entropy_bits, inbuflen<<3);
+
+	mutex_lock(&trng->lock);
+	ret = trng->crypto_cb->lrng_drng_seed_helper(trng->trng, inbuf,
+						      inbuflen);
+	if (ret < 0) {
+		pr_warn("(re)seeding of TRNG failed\n");
+		goto unlock;
+	}
+	pr_debug("inject %u bytes with %u bits of entropy into TRNG\n",
+		 inbuflen, entropy_bits);
+
+	/* Adjust the fill level indicator to at most the DRNG sec strength */
+	trng->trng_entropy_bits =
+		min_t(u32, trng->trng_entropy_bits + entropy_bits,
+		      LRNG_DRNG_SECURITY_STRENGTH_BITS);
+	lrng_init_ops(trng->trng_entropy_bits);
+
+	if (outbuf && outbuflen)
+		ret = lrng_trng_generate(outbuf, outbuflen, fullentropy);
+
+unlock:
+	mutex_unlock(&trng->lock);
+	lrng_reader_wakeup();
+
+	return ret;
+}
+
+/**
+ * Seed the TRNG from the internal noise sources and generate random data. The
+ * seeding and the generation of random data is an atomic operation.
+ *
+ * lrng_pool_trylock() must be invoked successfully by caller.
+ */
+int lrng_trng_seed(u8 *outbuf, u32 outbuflen, bool fullentropy, bool drain)
+{
+	struct entropy_buf entropy_buf __aligned(LRNG_KCAPI_ALIGN);
+	struct lrng_trng *trng = &lrng_trng;
+	u32 total_entropy_bits;
+	int ret = 0, retrieved = 0;
+
+	/* Get available entropy in primary DRNG */
+	if (trng->trng_entropy_bits>>3) {
+		mutex_lock(&trng->lock);
+		ret = lrng_trng_generate(outbuf, outbuflen, fullentropy);
+		mutex_unlock(&trng->lock);
+		if (ret > 0) {
+			retrieved += ret;
+			if (ret == outbuflen)
+				goto out;
+
+			outbuf += ret;
+			outbuflen -= ret;
+		}
+		/* Disregard error code as another generate request is below. */
+	}
+
+	mutex_lock(&trng->lock);
+	total_entropy_bits = lrng_fill_seed_buffer(trng->crypto_cb, trng->hash,
+						   &entropy_buf, drain);
+	mutex_unlock(&trng->lock);
+
+	pr_debug("reseed TRNG from internal noise sources with %u bits "
+		 "of entropy\n", total_entropy_bits);
+
+	ret = lrng_trng_inject((u8 *)&entropy_buf, sizeof(entropy_buf),
+				total_entropy_bits,
+				outbuf, outbuflen, fullentropy);
+
+	memzero_explicit(&entropy_buf, sizeof(entropy_buf));
+
+	if (ret > 0)
+		retrieved += ret;
+
+out:
+	/* Allow the seeding operation to be called again */
+	lrng_pool_unlock();
+
+	return (ret >= 0) ? retrieved : ret;
+}
+
+/**
+ * Obtain random data from TRNG with information theoretical entropy by
+ * triggering a reseed. The TRNG will only return as many random bytes as it
+ * was seeded with.
+ *
+ * @outbuf: buffer to store the random data in
+ * @outbuflen: length of outbuf
+ * @return: < 0 on error
+ *	    >= 0 the number of bytes that were obtained
+ */
+int lrng_trng_get(u8 *outbuf, u32 outbuflen)
+{
+	int ret;
+
+	if (!outbuf || !outbuflen)
+		return 0;
+
+	lrng_drngs_init_cc20();
+
+	if (lrng_pool_trylock())
+		return -EINPROGRESS;
+	ret = lrng_trng_seed(outbuf, outbuflen, true, true);
+	if (ret >= 0) {
+		pr_debug("read %d bytes of full entropy data from TRNG\n", ret);
+	} else {
+		/* This is no error, but we have not generated anything */
+		if (ret == -EINPROGRESS)
+			return 0;
+		pr_debug("reading data from TRNG failed: %d\n", ret);
+	}
+
+	return ret;
+}
+
+#ifdef CONFIG_LRNG_DRNG_SWITCH
+int lrng_trng_switch(const struct lrng_crypto_cb *cb)
+{
+	int ret;
+	u8 seed[LRNG_DRNG_SECURITY_STRENGTH_BYTES];
+	void *trng, *hash;
+
+	trng = cb->lrng_drng_alloc(LRNG_DRNG_SECURITY_STRENGTH_BYTES);
+	if (IS_ERR(trng))
+		return PTR_ERR(trng);
+
+	hash = cb->lrng_hash_alloc(seed, sizeof(seed));
+	if (IS_ERR(hash)) {
+		pr_warn("could not allocate new LRNG pool hash (%ld)\n",
+			PTR_ERR(hash));
+		cb->lrng_drng_dealloc(trng);
+		return PTR_ERR(hash);
+	}
+
+	/* Update primary DRNG */
+	mutex_lock(&lrng_trng.lock);
+	/* pull from existing DRNG to seed new DRNG */
+	ret = lrng_trng.crypto_cb->lrng_drng_generate_helper_full(
+					lrng_trng.trng, seed, sizeof(seed));
+	if (ret < 0) {
+		lrng_trng_reset();
+		pr_warn("getting random data from TRNG failed (%d)\n", ret);
+	} else {
+		/*
+		 * No change of the seed status as the old and new DRNG have
+		 * same security strength.
+		 */
+		ret = cb->lrng_drng_seed_helper(trng, seed, ret);
+		if (ret < 0) {
+			lrng_trng_reset();
+			pr_warn("seeding of new TRNG failed (%d)\n", ret);
+		} else {
+			pr_debug("seeded new TRNG instance from old TRNG "
+				 "instance\n");
+		}
+	}
+	memzero_explicit(seed, sizeof(seed));
+
+	if (!lrng_get_available())
+		lrng_trng_reset();
+	lrng_trng.crypto_cb->lrng_drng_dealloc(lrng_trng.trng);
+	lrng_trng.trng = trng;
+
+	lrng_trng.crypto_cb->lrng_hash_dealloc(lrng_trng.hash);
+	lrng_trng.hash = hash;
+
+	lrng_trng.crypto_cb = cb;
+
+	mutex_unlock(&lrng_trng.lock);
+
+	pr_info("TRNG allocated\n");
+
+	return ret;
+}
+#endif	/* CONFIG_LRNG_DRNG_SWITCH */
-- 
2.23.0





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v24 11/12] LRNG - add SP800-90B compliant health tests
  2019-11-11 18:17 [PATCH v24 00/12] /dev/random - a new approach with full SP800-90B compliance Stephan Müller
                   ` (9 preceding siblings ...)
  2019-11-11 18:24 ` [PATCH v24 10/12] LRNG - add TRNG support Stephan Müller
@ 2019-11-11 18:26 ` Stephan Müller
  2019-11-12 19:58   ` Alexander E. Patrakov
  2019-11-11 18:26 ` [PATCH v24 12/12] LRNG - add interface for gathering of raw entropy Stephan Müller
                   ` (3 subsequent siblings)
  14 siblings, 1 reply; 162+ messages in thread
From: Stephan Müller @ 2019-11-11 18:26 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

Implement health tests for LRNG's slow noise sources as mandated by
SP-800-90B The file contains the following health tests:

- stuck test: The stuck test calculates the first, second and third
  discrete derivative of the time stamp to be processed by the LFSR.
  Only if all three values are zero, the received time delta is
  considered to be non-stuck.

- SP800-90B Repetition Count Test (RCT): The LRNG uses an enhanced
  version of the RCT specified in SP800-90B section 4.4.1. Instead of
  counting identical back-to-back values, the input to the RCT is the
  counting of the stuck values during the processing of received
  interrupt events. The RCT is applied with alpha=2^-30 compliant to
  the recommendation of FIPS 140-2 IG 9.8. During the counting operation,
  the LRNG always calculates the RCT cut-off value of C. If that value
  exceeds the allowed cut-off value, the LRNG will trigger the health
  test failure discussed below. An error is logged to the kernel log
  that such RCT failure occurred. This test is only applied and
  enforced in FIPS mode, i.e. when the kernel compiled with
  CONFIG_CONFIG_FIPS is started with fips=1.

- SP800-90B Adaptive Proportion Test (APT): The LRNG implements the
  APT as defined in SP800-90B section 4.4.2. The assumed

The aforementioned health tests are applied to the first 1,024 time stamps
obtained from interrupt events. In case one error is identified for either
the RCT, or the APT, the collected entropy is invalidated and the
SP800-90B startup health test is restarted.

As long as the SP800-90B startup health test is not completed, all LRNG
random number output interfaces that may block will block and not generate
any data. This implies that only those potentially blocking interfaces are
defined to provide random numbers that are seeded with the interrupt noise
source being SP800-90B compliant. All other output interfaces will not be
affected by the SP800-90B startup test and thus are not considered
SP800-90B compliant.

At runtime, the SP800-90B APT and RCT are applied to each time stamp
generated for a received interrupt. When either the APT and RCT indicates
a noise source failure, the LRNG is reset to a state it has immediately
after boot:

- all entropy counters are set to zero

- the SP800-90B startup tests are re-performed which implies that
getrandom(2) would block again until new entropy was collected

To summarize, the following rules apply:

• SP800-90B compliant output interfaces

  - /dev/random

  - getrandom(2) system call

  -  get_random_bytes kernel-internal interface when being triggered by
     the callback registered with add_random_ready_callback

• SP800-90B non-compliant output interfaces

  - /dev/urandom

  - get_random_bytes kernel-internal interface called directly

  - randomize_page kernel-internal interface

  - get_random_u32 and get_random_u64 kernel-internal interfaces

  - get_random_u32_wait, get_random_u64_wait, get_random_int_wait, and
    get_random_long_wait kernel-internal interfaces

If either the RCT, or the APT health test fails irrespective whether
during initialization or runtime, the following actions occur:

  1. The entropy of the entire entropy pool is invalidated.

  2. The primary and all secondary DRNGs are reset which imply that they
     are treated as being not seeded and require a reseed during next
     invocation.

  3. The SP800-90B startup health test are initiated with all
     implications of the startup tests. That implies that from that point
     on, new events must be observed and its entropy must be inserted into
     the entropy pool before random numbers are calculated from the
     entropy pool.

Further details on the SP800-90B compliance and the availability of all
test tools required to perform all tests mandated by SP800-90B are
provided at [1].

The entire health testing code is compile-time configurable.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Kconfig       |  13 +
 drivers/char/lrng/Makefile      |   1 +
 drivers/char/lrng/lrng_health.c | 424 ++++++++++++++++++++++++++++++++
 3 files changed, 438 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_health.c

diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
index efc5f9aaa2a3..4373a1a19538 100644
--- a/drivers/char/lrng/Kconfig
+++ b/drivers/char/lrng/Kconfig
@@ -113,4 +113,17 @@ config LRNG_TRNG_SUPPORT
 	  With the TRNG support the /dev/random device will block
 	  if insufficient entropy is available.
 
+config LRNG_HEALTH_TESTS
+	bool "Enable noise source online health tests"
+	help
+	  The online health tests validate the noise source at
+	  runtime for fatal errors. These tests include SP800-90B
+	  compliant tests which are invoked if the system is booted
+	  with fips=1. In case of fatal errors during active
+	  SP800-90B tests, the issue is logged and the noise
+	  data is discarded. These tests are required for full
+	  compliance with SP800-90B.
+
+	  If unsure, say Y.
+
 endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index 1c72bc060bce..0713e9c0aa6e 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -15,3 +15,4 @@ obj-$(CONFIG_LRNG_DRBG)		+= lrng_drbg.o
 obj-$(CONFIG_LRNG_KCAPI)	+= lrng_kcapi.o
 obj-$(CONFIG_LRNG_JENT)		+= lrng_jent.o
 obj-$(CONFIG_LRNG_TRNG_SUPPORT)	+= lrng_trng.o
+obj-$(CONFIG_LRNG_HEALTH_TESTS)	+= lrng_health.o
diff --git a/drivers/char/lrng/lrng_health.c b/drivers/char/lrng/lrng_health.c
new file mode 100644
index 000000000000..b8d96cec1f71
--- /dev/null
+++ b/drivers/char/lrng/lrng_health.c
@@ -0,0 +1,424 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * Linux Random Number Generator (LRNG) Health Testing
+ *
+ * Copyright (C) 2019, Stephan Mueller <smueller@chronox.de>
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/fips.h>
+#include <linux/module.h>
+
+#include "lrng_internal.h"
+
+/* Stuck Test */
+struct lrng_stuck_test {
+	u32 last_time;		/* Stuck test: time of previous IRQ */
+	u32 last_delta;		/* Stuck test: delta of previous IRQ */
+	u32 last_delta2;	/* Stuck test: 2. time derivation of prev IRQ */
+};
+
+/* Repetition Count Test */
+struct lrng_rct {
+	atomic_t rct_count;	/* Number of stuck values */
+};
+
+/* Adaptive Proportion Test */
+struct lrng_apt {
+	/* Taken from SP800-90B sec 4.4.2 - significance level 2^-30 */
+#define LRNG_APT_CUTOFF		325
+	/* Data window size */
+#define LRNG_APT_WINDOW_SIZE	512
+	/* LSB of time stamp to process */
+#define LRNG_APT_LSB		16
+#define LRNG_APT_WORD_MASK	(LRNG_APT_LSB - 1)
+	atomic_t apt_count;		/* APT counter */
+	atomic_t apt_base;		/* APT base reference */
+
+	atomic_t apt_trigger;
+	bool apt_base_set;	/* Is APT base set? */
+};
+
+/* The health test code must operate lock-less */
+struct lrng_health {
+	struct lrng_rct rct;
+	struct lrng_apt apt;
+
+	bool health_test_enabled;
+
+	/* SP800-90B startup health tests */
+#define LRNG_SP80090B_STARTUP_SAMPLES  1024
+#define LRNG_SP80090B_STARTUP_BLOCKS   ((LRNG_SP80090B_STARTUP_SAMPLES + \
+					 LRNG_APT_WINDOW_SIZE - 1) /    \
+					LRNG_APT_WINDOW_SIZE)
+	bool sp80090b_startup_done;
+	atomic_t sp80090b_startup_blocks;
+};
+
+static struct lrng_health lrng_health = {
+	.rct.rct_count = ATOMIC_INIT(0),
+
+	.apt.apt_count = ATOMIC_INIT(0),
+	.apt.apt_base = ATOMIC_INIT(-1),
+	.apt.apt_trigger = ATOMIC_INIT(LRNG_APT_WINDOW_SIZE),
+	.apt.apt_base_set = false,
+
+	.health_test_enabled = true,
+
+	.sp80090b_startup_blocks = ATOMIC_INIT(LRNG_SP80090B_STARTUP_BLOCKS),
+	.sp80090b_startup_done = false,
+};
+
+static DEFINE_PER_CPU(struct lrng_stuck_test, lrng_stuck_test);
+
+static inline bool lrng_sp80090b_health_requested(void)
+{
+	/* Health tests are only requested in FIPS mode */
+	return fips_enabled;
+}
+
+static inline bool lrng_sp80090b_health_enabled(void)
+{
+	struct lrng_health *health = &lrng_health;
+
+	return lrng_sp80090b_health_requested() && health->health_test_enabled;
+}
+
+/***************************************************************************
+ * SP800-90B Compliance
+ *
+ * If the Linux-RNG is booted into FIPS mode, the following interfaces
+ * provide an SP800-90B compliant noise source:
+ *
+ * * /dev/random
+ * * getrandom(2)
+ * * get_random_bytes when using it in conjunction with
+ *   add_random_ready_callback
+ *
+ * All other interfaces, including /dev/urandom or get_random_bytes without
+ * the add_random_ready_callback cannot claim to use an SP800-90B compliant
+ * noise source.
+ ***************************************************************************/
+
+/**
+ * Perform SP800-90B startup testing
+ */
+static inline void lrng_sp80090b_startup(struct lrng_health *health)
+{
+	if (!health->sp80090b_startup_done &&
+	    atomic_dec_and_test(&health->sp80090b_startup_blocks)) {
+		health->sp80090b_startup_done = true;
+		pr_info("SP800-90B startup health tests completed\n");
+		lrng_init_ops(0);
+
+		/*
+		 * Force a reseed of secondary DRNGs to ensure they are
+		 * seeded with entropy that passed the SP800-90B health tests.
+		 * As the primary DRNG always will reseed before generating
+		 * random numbers, it does not need a reseed trigger.
+		 */
+		lrng_sdrng_force_reseed();
+	}
+}
+
+/**
+ * Handle failure of SP800-90B startup testing
+ */
+static inline void lrng_sp80090b_startup_failure(struct lrng_health *health)
+{
+	/* Reset of LRNG and its entropy - NOTE: we are in atomic context */
+	lrng_reset();
+
+	/*
+	 * Reset the SP800-90B startup test.
+	 *
+	 * NOTE SP800-90B section 4.3 bullet 4 does not specify what
+	 * exactly is to be done in case of failure! Thus, we do what
+	 * makes sense, i.e. restarting the health test and thus gating
+	 * the output function of /dev/random and getrandom(2).
+	 */
+	atomic_set(&health->sp80090b_startup_blocks,
+		   LRNG_SP80090B_STARTUP_BLOCKS);
+}
+
+/**
+ * Handle failure of SP800-90B runtime testing
+ */
+static inline void lrng_sp80090b_runtime_failure(struct lrng_health *health)
+{
+	lrng_sp80090b_startup_failure(health);
+	health->sp80090b_startup_done = false;
+}
+
+static inline void lrng_sp80090b_failure(struct lrng_health *health)
+{
+	if (health->sp80090b_startup_done) {
+		pr_err("SP800-90B runtime health test failure - invalidating "
+		       "all existing entropy and initiate SP800-90B startup\n");
+		lrng_sp80090b_runtime_failure(health);
+	} else {
+		pr_err("SP800-90B startup test failure - resetting\n");
+		lrng_sp80090b_startup_failure(health);
+	}
+}
+
+/**
+ * Is the SP800-90B startup testing complete?
+ *
+ * This function is called by the LRNG to determine whether to unblock
+ * a certain user interface. Therefore, only the potentially blocking
+ * user interfaces are considered SP800-90B compliant.
+ */
+bool lrng_sp80090b_startup_complete(void)
+{
+	struct lrng_health *health = &lrng_health;
+
+	return (lrng_sp80090b_health_enabled()) ? health->sp80090b_startup_done:
+						  true;
+}
+
+bool lrng_sp80090b_compliant(void)
+{
+	struct lrng_health *health = &lrng_health;
+
+	return lrng_sp80090b_health_enabled() && health->sp80090b_startup_done;
+}
+
+/***************************************************************************
+ * Adaptive Proportion Test
+ *
+ * This test complies with SP800-90B section 4.4.2.
+ ***************************************************************************/
+
+/**
+ * Reset the APT counter
+ *
+ * @health [in] Reference to health state
+ */
+static inline void lrng_apt_reset(struct lrng_health *health,
+				  unsigned int time_masked)
+{
+	struct lrng_apt *apt = &health->apt;
+
+	pr_debug("APT value %d for base %d\n",
+		 atomic_read(&apt->apt_count), atomic_read(&apt->apt_base));
+
+	/* Reset APT */
+	atomic_set(&apt->apt_count, 0);
+	atomic_set(&apt->apt_base, time_masked);
+}
+
+static inline void lrng_apt_restart(struct lrng_health *health)
+{
+	struct lrng_apt *apt = &health->apt;
+
+	atomic_set(&apt->apt_trigger, LRNG_APT_WINDOW_SIZE);
+}
+
+/**
+ * Insert a new entropy event into APT
+ *
+ * This function does is void as it does not decide about the fate of a time
+ * stamp. An APT failure can only happen at the same time of a stuck test
+ * failure. Thus, the stuck failure will already decide how the time stamp
+ * is handled.
+ *
+ * @health [in] Reference to health state
+ * @now_time [in] Time stamp to process
+ */
+static inline void lrng_apt_insert(struct lrng_health *health,
+				   unsigned int now_time)
+{
+	struct lrng_apt *apt = &health->apt;
+
+	if (!lrng_sp80090b_health_requested())
+		return;
+
+	now_time &= LRNG_APT_WORD_MASK;
+
+	/* Initialization of APT */
+	if (!apt->apt_base_set) {
+		atomic_set(&apt->apt_base, now_time);
+		apt->apt_base_set = true;
+		return;
+	}
+
+	if (now_time == (unsigned int)atomic_read(&apt->apt_base)) {
+		u32 apt_val = (u32)atomic_inc_return_relaxed(&apt->apt_count);
+
+		if (apt_val >= LRNG_APT_CUTOFF)
+			lrng_sp80090b_failure(health);
+	}
+
+	if (atomic_dec_and_test(&apt->apt_trigger)) {
+		lrng_apt_restart(health);
+		lrng_apt_reset(health, now_time);
+		lrng_sp80090b_startup(health);
+	}
+}
+
+/***************************************************************************
+ * Repetition Count Test
+ *
+ * The LRNG uses an enhanced version of the Repetition Count Test
+ * (RCT) specified in SP800-90B section 4.4.1. Instead of counting identical
+ * back-to-back values, the input to the RCT is the counting of the stuck
+ * values while filling the entropy pool.
+ *
+ * The RCT is applied with an alpha of 2^-30 compliant to FIPS 140-2 IG 9.8.
+ *
+ * During the counting operation, the LRNG always calculates the RCT
+ * cut-off value of C. If that value exceeds the allowed cut-off value,
+ * the LRNG will invalidate all entropy for the entropy pool which implies
+ * that no data can be extracted from the entropy pool unless new entropy
+ * is received.
+ ***************************************************************************/
+
+/**
+ * Hot code path - Insert data for Repetition Count Test
+ *
+ * @health: Reference to health information
+ * @stuck: Decision of stuck test
+ */
+static inline void lrng_rct(struct lrng_health *health, int stuck)
+{
+	struct lrng_rct *rct = &health->rct;
+
+	if (!lrng_sp80090b_health_requested())
+		return;
+
+	if (stuck) {
+		u32 rct_count = atomic_add_return_relaxed(1, &rct->rct_count);
+
+		pr_debug("RCT count: %u\n", rct_count);
+
+		/*
+		 * The cutoff value is based on the following consideration:
+		 * alpha = 2^-30 as recommended in FIPS 140-2 IG 9.8.
+		 * In addition, we imply an entropy value H of 1 bit as this
+		 * is the minimum entropy required to provide full entropy.
+		 *
+		 * Note, rct_count (which equals to value B in the
+		 * pseudo code of SP800-90B section 4.4.1) starts with zero.
+		 * Hence we need to subtract one from the cutoff value as
+		 * calculated following SP800-90B.
+		 */
+		if (rct_count >= 30) {
+			atomic_set(&rct->rct_count, 0);
+
+			/*
+			 * APT must start anew as we consider all previously
+			 * recorded data to contain no entropy.
+			 */
+			lrng_apt_restart(health);
+
+			lrng_sp80090b_failure(health);
+		}
+	} else {
+		atomic_set(&rct->rct_count, 0);
+	}
+}
+
+/***************************************************************************
+ * Stuck Test
+ *
+ * Checking the:
+ *      1st derivative of the event occurrence (time delta)
+ *      2nd derivative of the event occurrence (delta of time deltas)
+ *      3rd derivative of the event occurrence (delta of delta of time deltas)
+ *
+ * All values must always be non-zero. The stuck test is only valid disabled if
+ * high-resolution time stamps are identified after initialization.
+ ***************************************************************************/
+
+static inline u32 lrng_delta(u32 prev, u32 next)
+{
+	/*
+	 * Note that this (unsigned) subtraction does yield the correct value
+	 * in the wraparound-case, i.e. when next < prev.
+	 */
+	return (next - prev);
+}
+
+/**
+ * Hot code path
+ *
+ * @health: Reference to health information
+ * @now: Event time
+ * @return: 0 event occurrence not stuck (good time stamp)
+ *	    != 0 event occurrence stuck (reject time stamp)
+ */
+static inline int lrng_irq_stuck(struct lrng_stuck_test *stuck, u32 now_time)
+{
+	u32 delta = lrng_delta(stuck->last_time, now_time);
+	u32 delta2 = lrng_delta(stuck->last_delta, delta);
+	u32 delta3 = lrng_delta(stuck->last_delta2, delta2);
+
+	stuck->last_time = now_time;
+	stuck->last_delta = delta;
+	stuck->last_delta2 = delta2;
+
+	if (!delta || !delta2 || !delta3)
+		return 1;
+
+	return 0;
+}
+
+/***************************************************************************
+ * Health test interfaces
+ ***************************************************************************/
+
+/**
+ * Disable all health tests
+ */
+void lrng_health_disable(void)
+{
+	struct lrng_health *health = &lrng_health;
+
+	health->health_test_enabled = false;
+
+	if (lrng_sp80090b_health_requested())
+		pr_warn("SP800-90B compliance requested but the Linux RNG is "
+			"NOT SP800-90B compliant\n");
+}
+
+/**
+ * Hot code path - Perform health test on time stamp received from an event
+ *
+ * @now_time Time stap
+ */
+enum lrng_health_res lrng_health_test(u32 now_time)
+{
+	struct lrng_health *health = &lrng_health;
+	struct lrng_stuck_test *stuck_test = this_cpu_ptr(&lrng_stuck_test);
+	int stuck;
+
+	if (!health->health_test_enabled)
+		return lrng_health_pass;
+
+	lrng_apt_insert(health, now_time);
+
+	stuck = lrng_irq_stuck(stuck_test, now_time);
+	lrng_rct(health, stuck);
+	if (stuck) {
+		/* SP800-90B disallows using a failing health test time stamp */
+		return lrng_sp80090b_health_requested() ?
+			lrng_health_fail_drop : lrng_health_fail_use;
+	}
+
+	return lrng_health_pass;
+}
-- 
2.23.0





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v24 12/12] LRNG - add interface for gathering of raw entropy
  2019-11-11 18:17 [PATCH v24 00/12] /dev/random - a new approach with full SP800-90B compliance Stephan Müller
                   ` (10 preceding siblings ...)
  2019-11-11 18:26 ` [PATCH v24 11/12] LRNG - add SP800-90B compliant health tests Stephan Müller
@ 2019-11-11 18:26 ` Stephan Müller
  2019-11-12 20:55   ` kbuild test robot
  2019-11-12 13:23 ` [PATCH v24 00/12] /dev/random - a new approach with full SP800-90B compliance Florian Weimer
                   ` (2 subsequent siblings)
  14 siblings, 1 reply; 162+ messages in thread
From: Stephan Müller @ 2019-11-11 18:26 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

The test interface allows a privileged process to capture the raw
unconditioned noise that is collected by the LRNG for statistical
analysis. Extracted noise data is not used to seed the LRNG. This
is a test interface and not appropriate for production systems.
Yet, the interface is considered to be sufficiently secured for
production systems.

Access to the data is given through the lrng_raw debugfs file. The
data buffer should be multiples of sizeof(u32) to fill the entire
buffer. Using the option lrng_testing.boot_test=1 the raw noise of
the first 1000 entropy events since boot can be sampled.

This test interface allows generating the data required for
analysis whether the LRNG is in compliance with SP800-90B
sections 3.1.3 and 3.1.4.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Kconfig        |  16 ++
 drivers/char/lrng/Makefile       |   1 +
 drivers/char/lrng/lrng_testing.c | 324 +++++++++++++++++++++++++++++++
 3 files changed, 341 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_testing.c

diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
index 4373a1a19538..c3d7524b7698 100644
--- a/drivers/char/lrng/Kconfig
+++ b/drivers/char/lrng/Kconfig
@@ -126,4 +126,20 @@ config LRNG_HEALTH_TESTS
 
 	  If unsure, say Y.
 
+config LRNG_TESTING
+	bool "Enable entropy test interface to LRNG noise source"
+	select CONFIG_DEBUG_FS
+	help
+	  The test interface allows a privileged process to capture
+	  the raw unconditioned noise that is collected by the LRNG
+	  for statistical analysis. Extracted noise data is not used
+	  to seed the LRNG.
+
+	  The raw noise data can be obtained using the lrng_raw
+	  debugfs file. Using the option lrng_testing.boot_test=1
+	  the raw noise of the first 1000 entropy events since boot
+	  can be sampled.
+
+	  If unsure, say N.
+
 endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index 0713e9c0aa6e..c0b6cc4301fe 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -16,3 +16,4 @@ obj-$(CONFIG_LRNG_KCAPI)	+= lrng_kcapi.o
 obj-$(CONFIG_LRNG_JENT)		+= lrng_jent.o
 obj-$(CONFIG_LRNG_TRNG_SUPPORT)	+= lrng_trng.o
 obj-$(CONFIG_LRNG_HEALTH_TESTS)	+= lrng_health.o
+obj-$(CONFIG_LRNG_TESTING)	+= lrng_testing.o
diff --git a/drivers/char/lrng/lrng_testing.c b/drivers/char/lrng/lrng_testing.c
new file mode 100644
index 000000000000..584bf926c05b
--- /dev/null
+++ b/drivers/char/lrng/lrng_testing.c
@@ -0,0 +1,324 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * Linux Random Number Generator (LRNG) Raw entropy collection tool
+ *
+ * Copyright (C) 2019, Stephan Mueller <smueller@chronox.de>
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/atomic.h>
+#include <linux/bug.h>
+#include <linux/debugfs.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/sched/signal.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+#include <linux/workqueue.h>
+#include <asm/errno.h>
+
+#include "lrng_internal.h"
+
+#define LRNG_TESTING_RINGBUFFER_SIZE	1024
+#define LRNG_TESTING_RINGBUFFER_MASK	(LRNG_TESTING_RINGBUFFER_SIZE - 1)
+
+static u32 lrng_testing_rb[LRNG_TESTING_RINGBUFFER_SIZE];
+static atomic_t lrng_rb_reader = ATOMIC_INIT(0);
+static atomic_t lrng_rb_writer = ATOMIC_INIT(0);
+static atomic_t lrng_rb_first_in = ATOMIC_INIT(0);
+static atomic_t lrng_testing_enabled = ATOMIC_INIT(0);
+
+static DECLARE_WAIT_QUEUE_HEAD(lrng_raw_read_wait);
+
+static u32 boot_test = 0;
+module_param(boot_test, uint, 0644);
+MODULE_PARM_DESC(boot_test, "Enable gathering boot time entropy of the first"
+			    " entropy events");
+
+static inline void lrng_raw_entropy_reset(void)
+{
+	atomic_set(&lrng_rb_reader, 0);
+	atomic_set(&lrng_rb_writer, 0);
+	atomic_set(&lrng_rb_first_in, 0);
+}
+
+static void lrng_raw_entropy_init(void)
+{
+	/*
+	 * The boot time testing implies we have a running test. If the
+	 * caller wants to clear it, he has to unset the boot_test flag
+	 * at runtime via sysfs to enable regular runtime testing
+	 */
+	if (boot_test)
+		return;
+
+	lrng_raw_entropy_reset();
+	atomic_set(&lrng_testing_enabled, 1);
+	pr_warn("Enabling raw entropy collection\n");
+}
+
+static void lrng_raw_entropy_fini(void)
+{
+	if (boot_test)
+		return;
+
+	lrng_raw_entropy_reset();
+	atomic_set(&lrng_testing_enabled, 0);
+	pr_warn("Disabling raw entropy collection\n");
+}
+
+bool lrng_raw_entropy_store(u32 value)
+{
+	unsigned int write_ptr;
+	unsigned int read_ptr;
+
+	if (!atomic_read(&lrng_testing_enabled) && !boot_test)
+		return false;
+
+	write_ptr = (unsigned int)atomic_add_return_relaxed(1, &lrng_rb_writer);
+	read_ptr = (unsigned int)atomic_read(&lrng_rb_reader);
+
+	/*
+	 * Disable entropy testing for boot time testing after ring buffer
+	 * is filled.
+	 */
+	if (boot_test && write_ptr > LRNG_TESTING_RINGBUFFER_SIZE) {
+		pr_warn_once("Boot time entropy collection test disabled\n");
+		return false;
+	}
+
+	if (boot_test && !atomic_read(&lrng_rb_first_in))
+		pr_warn("Boot time entropy collection test enabled\n");
+
+	lrng_testing_rb[write_ptr & LRNG_TESTING_RINGBUFFER_MASK] = value;
+
+	/* We got at least one event, enable the reader now. */
+	atomic_set(&lrng_rb_first_in, 1);
+
+	if (wq_has_sleeper(&lrng_raw_read_wait))
+		wake_up_interruptible(&lrng_raw_read_wait);
+
+	/*
+	 * Our writer is taking over the reader - this means the reader
+	 * one full ring buffer available. Thus we "push" the reader ahead
+	 * to guarantee that he will be able to consume the full ring.
+	 */
+	if (!boot_test &&
+	    ((write_ptr & LRNG_TESTING_RINGBUFFER_MASK) ==
+	    (read_ptr & LRNG_TESTING_RINGBUFFER_MASK)))
+		atomic_inc_return_relaxed(&lrng_rb_reader);
+
+	return true;
+}
+
+static inline bool lrng_raw_have_data(void)
+{
+	unsigned int read_ptr = (unsigned int)atomic_read(&lrng_rb_reader);
+	unsigned int write_ptr = (unsigned int)atomic_read(&lrng_rb_writer);
+
+	return (atomic_read(&lrng_rb_first_in) &&
+		(write_ptr & LRNG_TESTING_RINGBUFFER_MASK) !=
+		 (read_ptr & LRNG_TESTING_RINGBUFFER_MASK));
+}
+
+static int lrng_raw_entropy_reader(u8 *outbuf, u32 outbuflen)
+{
+	int collected_data = 0;
+
+	if (!atomic_read(&lrng_testing_enabled) && !boot_test)
+		return -EAGAIN;
+
+	if (!atomic_read(&lrng_rb_first_in)) {
+		wait_event_interruptible(lrng_raw_read_wait,
+					 lrng_raw_have_data());
+		if (signal_pending(current))
+			return -ERESTARTSYS;
+	}
+
+	while (outbuflen) {
+		unsigned int read_ptr =
+			(unsigned int)atomic_add_return_relaxed(
+							1, &lrng_rb_reader);
+		unsigned int write_ptr =
+			(unsigned int)atomic_read(&lrng_rb_writer);
+
+		/*
+		 * For boot time testing, only output one round of ring buffer.
+		 */
+		if (boot_test && read_ptr > LRNG_TESTING_RINGBUFFER_SIZE) {
+			collected_data = -ENOMSG;
+			goto out;
+		}
+
+		/* We reached the writer */
+		if (!boot_test && ((write_ptr & LRNG_TESTING_RINGBUFFER_MASK) ==
+		    (read_ptr & LRNG_TESTING_RINGBUFFER_MASK))) {
+			wait_event_interruptible(lrng_raw_read_wait,
+						 lrng_raw_have_data());
+			if (signal_pending(current))
+				return -ERESTARTSYS;
+
+			continue;
+		}
+
+		/* We copy out word-wise */
+		if (outbuflen < sizeof(u32)) {
+			atomic_dec_return_relaxed(&lrng_rb_reader);
+			goto out;
+		}
+
+		memcpy(outbuf,
+		       &lrng_testing_rb[read_ptr & LRNG_TESTING_RINGBUFFER_MASK],
+		       sizeof(u32));
+		outbuf += sizeof(u32);
+		outbuflen -= sizeof(u32);
+		collected_data += sizeof(u32);
+	}
+
+out:
+	return collected_data;
+}
+
+/**************************************************************************
+ * Debugfs interface
+ **************************************************************************/
+static int lrng_raw_extract_user(void __user *buf, size_t nbytes)
+{
+	u8 tmp[LRNG_TESTING_RINGBUFFER_SIZE] __aligned(sizeof(u32));
+	int ret = 0, large_request = (nbytes > 256);
+
+	while (nbytes) {
+		int i;
+
+		if (large_request && need_resched()) {
+			if (signal_pending(current)) {
+				if (ret == 0)
+					ret = -ERESTARTSYS;
+				break;
+			}
+			schedule();
+		}
+
+		i = min_t(int, nbytes, sizeof(tmp));
+		i = lrng_raw_entropy_reader(tmp, i);
+		if (i <= 0) {
+			if (i < 0)
+				ret = i;
+			break;
+		}
+		if (copy_to_user(buf, tmp, i)) {
+			ret = -EFAULT;
+			break;
+		}
+
+		nbytes -= i;
+		buf = (u8 *)buf + i;
+		ret += i;
+	}
+
+	memzero_explicit(tmp, sizeof(tmp));
+
+	return ret;
+}
+
+/*
+ * This data structure holds the dentry's of the debugfs files establishing
+ * the interface to user space.
+ */
+struct lrng_raw_debugfs {
+	struct dentry *lrng_raw_debugfs_root; /* root dentry */
+	struct dentry *lrng_raw_debugfs_lrng_raw; /* .../lrng_raw */
+};
+
+static struct lrng_raw_debugfs lrng_raw_debugfs;
+
+/* DebugFS operations and definition of the debugfs files */
+static ssize_t lrng_raw_read(struct file *file, char __user *to,
+			     size_t count, loff_t *ppos)
+{
+	loff_t pos = *ppos;
+	int ret;
+
+	if (!count)
+		return 0;
+	lrng_raw_entropy_init();
+	ret = lrng_raw_extract_user(to, count);
+	lrng_raw_entropy_fini();
+	if (ret < 0)
+		return ret;
+	count -= ret;
+	*ppos = pos + count;
+	return ret;
+}
+
+/* Module init: allocate memory, register the debugfs files */
+static int lrng_raw_debugfs_init(void)
+{
+	lrng_raw_debugfs.lrng_raw_debugfs_root =
+		debugfs_create_dir(KBUILD_MODNAME, NULL);
+	if (IS_ERR(lrng_raw_debugfs.lrng_raw_debugfs_root)) {
+		lrng_raw_debugfs.lrng_raw_debugfs_root = NULL;
+		return PTR_ERR(lrng_raw_debugfs.lrng_raw_debugfs_root);
+	}
+	return 0;
+}
+
+static struct file_operations lrng_raw_name_fops = {
+	.owner = THIS_MODULE,
+	.read = lrng_raw_read,
+};
+
+static int lrng_raw_debugfs_init_name(void)
+{
+	lrng_raw_debugfs.lrng_raw_debugfs_lrng_raw =
+		debugfs_create_file("lrng_raw", 0400,
+				    lrng_raw_debugfs.lrng_raw_debugfs_root,
+				    NULL, &lrng_raw_name_fops);
+	if (IS_ERR(lrng_raw_debugfs.lrng_raw_debugfs_lrng_raw)) {
+		lrng_raw_debugfs.lrng_raw_debugfs_lrng_raw = NULL;
+		return PTR_ERR(lrng_raw_debugfs.lrng_raw_debugfs_lrng_raw);
+	}
+	return 0;
+}
+
+static int __init lrng_raw_init(void)
+{
+	int ret = lrng_raw_debugfs_init();
+
+	if (ret < 0)
+		return ret;
+
+	ret = lrng_raw_debugfs_init_name();
+	if (ret < 0)
+		debugfs_remove_recursive(
+					lrng_raw_debugfs.lrng_raw_debugfs_root);
+
+	return ret;
+}
+
+static void __exit lrng_raw_exit(void)
+{
+	debugfs_remove_recursive(lrng_raw_debugfs.lrng_raw_debugfs_root);
+}
+
+module_init(lrng_raw_init);
+module_exit(lrng_raw_exit);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
+MODULE_DESCRIPTION("Kernel module for gathering raw entropy");
-- 
2.23.0





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* Re: [PATCH v24 01/12] Linux Random Number Generator
  2019-11-11 18:18 ` [PATCH v24 01/12] Linux Random Number Generator Stephan Müller
@ 2019-11-11 23:54   ` Thomas Gleixner
  2019-11-12  2:25     ` Stephan Müller
  2019-11-12 22:30   ` kbuild test robot
                     ` (2 subsequent siblings)
  3 siblings, 1 reply; 162+ messages in thread
From: Thomas Gleixner @ 2019-11-11 23:54 UTC (permalink / raw)
  To: Stephan Müller
  Cc: Arnd Bergmann, Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

[-- Attachment #1: Type: text/plain, Size: 1789 bytes --]

Stephan,

On Mon, 11 Nov 2019, Stephan Müller wrote:

thanks for Cc'ing me. I'll have a look at the technical details at later
point in time. While skimming through the patches I noticed, that you
thankfully added the SPDX license identifiers, but

> @@ -0,0 +1,105 @@
> +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
> +/*
> + * LRNG Fast Noise Source: CPU-based noise source
> + *
> + * Copyright (C) 2016 - 2019, Stephan Mueller <smueller@chronox.de>
> + *
> + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
> + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
> + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
> + * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
> + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
> + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
> + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
> + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
> + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
> + * DAMAGE.

we really want to get rid of these boiler plate disclaimers as they are
already implicit by the SPDX license identifier and provide no real
value.

Aside of that, the above disclaimer has even a slightly different wording
than the standard BSD-2-Clause disclaimer which is going to cause even more
headaches as automated scanner tools will detect that and someone has to go
through that unreadable uppercase yelling mess and figure out whether it's
a legaly substantial difference.

Can you please get rid of those?

Thanks,

	tglx


^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v24 01/12] Linux Random Number Generator
  2019-11-11 23:54   ` Thomas Gleixner
@ 2019-11-12  2:25     ` Stephan Müller
  2019-11-12 10:16       ` Thomas Gleixner
  0 siblings, 1 reply; 162+ messages in thread
From: Stephan Müller @ 2019-11-12  2:25 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Arnd Bergmann, Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

Am Dienstag, 12. November 2019, 00:54:16 CET schrieb Thomas Gleixner:

Hi Thomas,

> Stephan,
> 
> On Mon, 11 Nov 2019, Stephan Müller wrote:
> 
> thanks for Cc'ing me. I'll have a look at the technical details at later
> point in time. 

Thank you very much for considering a review.

> While skimming through the patches I noticed, that you
> thankfully added the SPDX license identifiers, but
> 
> > @@ -0,0 +1,105 @@
> > +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
> > +/*
> > + * LRNG Fast Noise Source: CPU-based noise source
> > + *
> > + * Copyright (C) 2016 - 2019, Stephan Mueller <smueller@chronox.de>
> > + *
> > + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
> > + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
> > + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
> > + * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
> > + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> > + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
> > + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
> > + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
> > + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> > + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
> > + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
> > + * DAMAGE.
> 
> we really want to get rid of these boiler plate disclaimers as they are
> already implicit by the SPDX license identifier and provide no real
> value.
> 
> Aside of that, the above disclaimer has even a slightly different wording
> than the standard BSD-2-Clause disclaimer which is going to cause even more
> headaches as automated scanner tools will detect that and someone has to go
> through that unreadable uppercase yelling mess and figure out whether it's
> a legaly substantial difference.
> 
> Can you please get rid of those?

Absolutely. I have removed that boiler plate disclaimer from all files.

Though I hope it is acceptable to wait for further comments before a 
resubmission.

Thank you very much.

Ciao
Stephan



^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v24 01/12] Linux Random Number Generator
  2019-11-12  2:25     ` Stephan Müller
@ 2019-11-12 10:16       ` Thomas Gleixner
  0 siblings, 0 replies; 162+ messages in thread
From: Thomas Gleixner @ 2019-11-12 10:16 UTC (permalink / raw)
  To: Stephan Müller
  Cc: Arnd Bergmann, Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

[-- Attachment #1: Type: text/plain, Size: 344 bytes --]

On Tue, 12 Nov 2019, Stephan Müller wrote:
> Am Dienstag, 12. November 2019, 00:54:16 CET schrieb Thomas Gleixner:
> > Can you please get rid of those?
> 
> Absolutely. I have removed that boiler plate disclaimer from all files.

Appreciated.

> Though I hope it is acceptable to wait for further comments before a 
> resubmission.

Of course!

^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v24 00/12] /dev/random - a new approach with full SP800-90B compliance
  2019-11-11 18:17 [PATCH v24 00/12] /dev/random - a new approach with full SP800-90B compliance Stephan Müller
                   ` (11 preceding siblings ...)
  2019-11-11 18:26 ` [PATCH v24 12/12] LRNG - add interface for gathering of raw entropy Stephan Müller
@ 2019-11-12 13:23 ` Florian Weimer
  2019-11-12 22:43   ` Stephan Müller
  2019-11-12 15:33 ` Andy Lutomirski
  2019-11-16  9:32 ` [PATCH v25 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
  14 siblings, 1 reply; 162+ messages in thread
From: Florian Weimer @ 2019-11-12 13:23 UTC (permalink / raw)
  To: Stephan Müller
  Cc: Arnd Bergmann, Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

* Stephan Müller:

> * support deactivation of TRNG (i.e. blocking behavior of /dev/random)
>   at compile time. If deactivated, /dev/random behaves like
>   getrandom(2).

I don't quite understand this comment.  Doesn't getrandom with the
GRND_RANDOM always behave like /dev/random?  Presumably, without the
TRNG tap, the GRND_RANDOM flag for getrandom is ignored, and reading
from /dev/random behaves like reading from /dev/urandom.

Anyway, reading the accompanying PDF, this looks rather impressive:
the userspace bootstrapping problem is gone (the issue where waiting
for more entropy prevents the collection of more entropy), *and* we
can still make the standards people happy.

(Replying from my other account due to mail issues, sorry.)

^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v24 00/12] /dev/random - a new approach with full SP800-90B compliance
  2019-11-11 18:17 [PATCH v24 00/12] /dev/random - a new approach with full SP800-90B compliance Stephan Müller
                   ` (12 preceding siblings ...)
  2019-11-12 13:23 ` [PATCH v24 00/12] /dev/random - a new approach with full SP800-90B compliance Florian Weimer
@ 2019-11-12 15:33 ` Andy Lutomirski
  2019-11-12 23:03   ` Stephan Müller
  2019-11-13  4:24   ` Stephan Müller
  2019-11-16  9:32 ` [PATCH v25 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
  14 siblings, 2 replies; 162+ messages in thread
From: Andy Lutomirski @ 2019-11-12 15:33 UTC (permalink / raw)
  To: Stephan Müller
  Cc: Arnd Bergmann, Greg Kroah-Hartman, Linux Crypto Mailing List,
	LKML, Linux API, Eric W. Biederman, Alexander E. Patrakov,
	Ahmed S. Darwish, Theodore Y. Ts'o, Willy Tarreau,
	Matthew Garrett, Vito Caputo, Andreas Dilger, Jan Kara,
	Ray Strode, William Jon McCann, zhangjs, Andy Lutomirski,
	Florian Weimer, Lennart Poettering, Nicolai Stange, Peter,
	Matthias, Marcelo Henrique Cerri, Roman Drahtmueller,
	Neil Horman

On Mon, Nov 11, 2019 at 11:13 AM Stephan Müller <smueller@chronox.de> wrote:
>
> The following patch set provides a different approach to /dev/random which is
> called Linux Random Number Generator (LRNG) to collect entropy within the Linux
> kernel. The main improvements compared to the existing /dev/random is to provide
> sufficient entropy during boot time as well as in virtual environments and when
> using SSDs. A secondary design goal is to limit the impact of the entropy
> collection on massive parallel systems and also allow the use accelerated
> cryptographic primitives. Also, all steps of the entropic data processing are
> testable.

This is very nice!

>
> The LRNG patch set allows a user to select use of the existing /dev/random or
> the LRNG during compile time. As the LRNG provides API and ABI compatible
> interfaces to the existing /dev/random implementation, the user can freely chose
> the RNG implementation without affecting kernel or user space operations.
>
> This patch set provides early boot-time entropy which implies that no
> additional flags to the getrandom(2) system call discussed recently on
> the LKML is considered to be necessary.

I'm uneasy about this.  I fully believe that, *on x86*, this works.
But on embedded systems with in-order CPUs, a single clock, and very
lightweight boot processes, most or all of boot might be too
deterministic for this to work.

I have a somewhat competing patch set here:

https://git.kernel.org/pub/scm/linux/kernel/git/luto/linux.git/log/?h=random/kill-it

(Ignore the "horrible test hack" and the debugfs part.)

The basic summary is that I change /dev/random so that it becomes
functionally identical to getrandom(..., 0) -- in other words, it
blocks until the CRNG is initialized but is then identical to
/dev/urandom.  And I add getrandom(...., GRND_INSECURE) that is
functionally identical to the existing /dev/urandom: it always returns
*something* immediately, but it may or may not actually be
cryptographically random or even random at all depending on system
details.

In other words, my series simplifies the ABI that we support.  Right
now, we have three ways to ask for random numbers with different
semantics and we need to have to RNGs in the kernel at all time.  With
my changes, we have only two ways to ask for random numbers, and the
/dev/random pool is entirely gone.

Would you be amenable to merging this into your series (i.e. either
merging the code or just the ideas)?  This would let you get rid of
things like the compile-time selection of the blocking TRNG, since the
blocking TRNG would be entirely gone.

Or do you think that a kernel-provided blocking TRNG is a genuinely
useful thing to keep around?

--Andy

^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v24 11/12] LRNG - add SP800-90B compliant health tests
  2019-11-11 18:26 ` [PATCH v24 11/12] LRNG - add SP800-90B compliant health tests Stephan Müller
@ 2019-11-12 19:58   ` Alexander E. Patrakov
  2019-11-12 23:11     ` Stephan Müller
  2019-11-13  0:36     ` Stephan Müller
  0 siblings, 2 replies; 162+ messages in thread
From: Alexander E. Patrakov @ 2019-11-12 19:58 UTC (permalink / raw)
  To: Stephan Müller, Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Ahmed S. Darwish, Theodore Y. Ts'o,
	Willy Tarreau, Matthew Garrett, Vito Caputo, Andreas Dilger,
	Jan Kara, Ray Strode, William Jon McCann, zhangjs,
	Andy Lutomirski, Florian Weimer, Lennart Poettering,
	Nicolai Stange, Peter, Matthias, Marcelo Henrique Cerri,
	Roman Drahtmueller, Neil Horman

[-- Attachment #1: Type: text/plain, Size: 21527 bytes --]

11.11.2019 23:26, Stephan Müller пишет:
> Implement health tests for LRNG's slow noise sources as mandated by
> SP-800-90B The file contains the following health tests:
> 
> - stuck test: The stuck test calculates the first, second and third
>    discrete derivative of the time stamp to be processed by the LFSR.
>    Only if all three values are zero, the received time delta is
>    considered to be non-stuck.

The other way round?
> 
> - SP800-90B Repetition Count Test (RCT): The LRNG uses an enhanced
>    version of the RCT specified in SP800-90B section 4.4.1. Instead of
>    counting identical back-to-back values, the input to the RCT is the
>    counting of the stuck values during the processing of received
>    interrupt events. The RCT is applied with alpha=2^-30 compliant to
>    the recommendation of FIPS 140-2 IG 9.8. During the counting operation,
>    the LRNG always calculates the RCT cut-off value of C. If that value
>    exceeds the allowed cut-off value, the LRNG will trigger the health
>    test failure discussed below. An error is logged to the kernel log
>    that such RCT failure occurred. This test is only applied and
>    enforced in FIPS mode, i.e. when the kernel compiled with
>    CONFIG_CONFIG_FIPS is started with fips=1.
> 
> - SP800-90B Adaptive Proportion Test (APT): The LRNG implements the
>    APT as defined in SP800-90B section 4.4.2. The assumed

The sentence ends in the middle.

> 
> The aforementioned health tests are applied to the first 1,024 time stamps
> obtained from interrupt events. In case one error is identified for either
> the RCT, or the APT, the collected entropy is invalidated and the
> SP800-90B startup health test is restarted.
> 
> As long as the SP800-90B startup health test is not completed, all LRNG
> random number output interfaces that may block will block and not generate
> any data. This implies that only those potentially blocking interfaces are
> defined to provide random numbers that are seeded with the interrupt noise
> source being SP800-90B compliant. All other output interfaces will not be
> affected by the SP800-90B startup test and thus are not considered
> SP800-90B compliant.
> 
> At runtime, the SP800-90B APT and RCT are applied to each time stamp
> generated for a received interrupt. When either the APT and RCT indicates
> a noise source failure, the LRNG is reset to a state it has immediately
> after boot:
> 
> - all entropy counters are set to zero
> 
> - the SP800-90B startup tests are re-performed which implies that
> getrandom(2) would block again until new entropy was collected
> 
> To summarize, the following rules apply:
> 
> • SP800-90B compliant output interfaces
> 
>    - /dev/random
> 
>    - getrandom(2) system call
> 
>    -  get_random_bytes kernel-internal interface when being triggered by
>       the callback registered with add_random_ready_callback
> 
> • SP800-90B non-compliant output interfaces
> 
>    - /dev/urandom
> 
>    - get_random_bytes kernel-internal interface called directly
> 
>    - randomize_page kernel-internal interface
> 
>    - get_random_u32 and get_random_u64 kernel-internal interfaces
> 
>    - get_random_u32_wait, get_random_u64_wait, get_random_int_wait, and
>      get_random_long_wait kernel-internal interfaces
> 
> If either the RCT, or the APT health test fails irrespective whether
> during initialization or runtime, the following actions occur:
> 
>    1. The entropy of the entire entropy pool is invalidated.
> 
>    2. The primary and all secondary DRNGs are reset which imply that they
>       are treated as being not seeded and require a reseed during next
>       invocation.
> 
>    3. The SP800-90B startup health test are initiated with all
>       implications of the startup tests. That implies that from that point
>       on, new events must be observed and its entropy must be inserted into
>       the entropy pool before random numbers are calculated from the
>       entropy pool.
> 
> Further details on the SP800-90B compliance and the availability of all
> test tools required to perform all tests mandated by SP800-90B are
> provided at [1].
> 
> The entire health testing code is compile-time configurable.
> 
> CC: "Eric W. Biederman" <ebiederm@xmission.com>
> CC: "Alexander E. Patrakov" <patrakov@gmail.com>
> CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
> CC: "Theodore Y. Ts'o" <tytso@mit.edu>
> CC: Willy Tarreau <w@1wt.eu>
> CC: Matthew Garrett <mjg59@srcf.ucam.org>
> CC: Vito Caputo <vcaputo@pengaru.com>
> CC: Andreas Dilger <adilger.kernel@dilger.ca>
> CC: Jan Kara <jack@suse.cz>
> CC: Ray Strode <rstrode@redhat.com>
> CC: William Jon McCann <mccann@jhu.edu>
> CC: zhangjs <zachary@baishancloud.com>
> CC: Andy Lutomirski <luto@kernel.org>
> CC: Florian Weimer <fweimer@redhat.com>
> CC: Lennart Poettering <mzxreary@0pointer.de>
> CC: Nicolai Stange <nstange@suse.de>
> Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
> Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
> Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
> Tested-by: Neil Horman <nhorman@redhat.com>
> Signed-off-by: Stephan Mueller <smueller@chronox.de>
> ---
>   drivers/char/lrng/Kconfig       |  13 +
>   drivers/char/lrng/Makefile      |   1 +
>   drivers/char/lrng/lrng_health.c | 424 ++++++++++++++++++++++++++++++++
>   3 files changed, 438 insertions(+)
>   create mode 100644 drivers/char/lrng/lrng_health.c
> 
> diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
> index efc5f9aaa2a3..4373a1a19538 100644
> --- a/drivers/char/lrng/Kconfig
> +++ b/drivers/char/lrng/Kconfig
> @@ -113,4 +113,17 @@ config LRNG_TRNG_SUPPORT
>   	  With the TRNG support the /dev/random device will block
>   	  if insufficient entropy is available.
>   
> +config LRNG_HEALTH_TESTS
> +	bool "Enable noise source online health tests"
> +	help
> +	  The online health tests validate the noise source at
> +	  runtime for fatal errors. These tests include SP800-90B
> +	  compliant tests which are invoked if the system is booted
> +	  with fips=1. In case of fatal errors during active
> +	  SP800-90B tests, the issue is logged and the noise
> +	  data is discarded. These tests are required for full
> +	  compliance with SP800-90B.

How have you tested that these tests work at runtime? Maybe add some 
code under a new CONFIG item that depends on CONFIG_BROKEN that 
deliberately botches the RNG and triggers failures?

> +
> +	  If unsure, say Y.
> +
>   endif # LRNG
> diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
> index 1c72bc060bce..0713e9c0aa6e 100644
> --- a/drivers/char/lrng/Makefile
> +++ b/drivers/char/lrng/Makefile
> @@ -15,3 +15,4 @@ obj-$(CONFIG_LRNG_DRBG)		+= lrng_drbg.o
>   obj-$(CONFIG_LRNG_KCAPI)	+= lrng_kcapi.o
>   obj-$(CONFIG_LRNG_JENT)		+= lrng_jent.o
>   obj-$(CONFIG_LRNG_TRNG_SUPPORT)	+= lrng_trng.o
> +obj-$(CONFIG_LRNG_HEALTH_TESTS)	+= lrng_health.o
> diff --git a/drivers/char/lrng/lrng_health.c b/drivers/char/lrng/lrng_health.c
> new file mode 100644
> index 000000000000..b8d96cec1f71
> --- /dev/null
> +++ b/drivers/char/lrng/lrng_health.c
> @@ -0,0 +1,424 @@
> +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
> +/*
> + * Linux Random Number Generator (LRNG) Health Testing
> + *
> + * Copyright (C) 2019, Stephan Mueller <smueller@chronox.de>
> + *
> + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
> + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
> + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
> + * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
> + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
> + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
> + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
> + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
> + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
> + * DAMAGE.
> + */
> +
> +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> +
> +#include <linux/fips.h>
> +#include <linux/module.h>
> +
> +#include "lrng_internal.h"
> +
> +/* Stuck Test */
> +struct lrng_stuck_test {
> +	u32 last_time;		/* Stuck test: time of previous IRQ */
> +	u32 last_delta;		/* Stuck test: delta of previous IRQ */
> +	u32 last_delta2;	/* Stuck test: 2. time derivation of prev IRQ */
> +};
> +
> +/* Repetition Count Test */
> +struct lrng_rct {
> +	atomic_t rct_count;	/* Number of stuck values */
> +};
> +
> +/* Adaptive Proportion Test */
> +struct lrng_apt {
> +	/* Taken from SP800-90B sec 4.4.2 - significance level 2^-30 */
> +#define LRNG_APT_CUTOFF		325
> +	/* Data window size */
> +#define LRNG_APT_WINDOW_SIZE	512
> +	/* LSB of time stamp to process */
> +#define LRNG_APT_LSB		16
> +#define LRNG_APT_WORD_MASK	(LRNG_APT_LSB - 1)
> +	atomic_t apt_count;		/* APT counter */
> +	atomic_t apt_base;		/* APT base reference */
> +
> +	atomic_t apt_trigger;
> +	bool apt_base_set;	/* Is APT base set? */
> +};
> +
> +/* The health test code must operate lock-less */
> +struct lrng_health {
> +	struct lrng_rct rct;
> +	struct lrng_apt apt;
> +
> +	bool health_test_enabled;
> +
> +	/* SP800-90B startup health tests */
> +#define LRNG_SP80090B_STARTUP_SAMPLES  1024
> +#define LRNG_SP80090B_STARTUP_BLOCKS   ((LRNG_SP80090B_STARTUP_SAMPLES + \
> +					 LRNG_APT_WINDOW_SIZE - 1) /    \
> +					LRNG_APT_WINDOW_SIZE)
> +	bool sp80090b_startup_done;
> +	atomic_t sp80090b_startup_blocks;
> +};
> +
> +static struct lrng_health lrng_health = {
> +	.rct.rct_count = ATOMIC_INIT(0),
> +
> +	.apt.apt_count = ATOMIC_INIT(0),
> +	.apt.apt_base = ATOMIC_INIT(-1),
> +	.apt.apt_trigger = ATOMIC_INIT(LRNG_APT_WINDOW_SIZE),
> +	.apt.apt_base_set = false,
> +
> +	.health_test_enabled = true,
> +
> +	.sp80090b_startup_blocks = ATOMIC_INIT(LRNG_SP80090B_STARTUP_BLOCKS),
> +	.sp80090b_startup_done = false,
> +};
> +
> +static DEFINE_PER_CPU(struct lrng_stuck_test, lrng_stuck_test);
> +
> +static inline bool lrng_sp80090b_health_requested(void)
> +{
> +	/* Health tests are only requested in FIPS mode */
> +	return fips_enabled;
> +}
> +
> +static inline bool lrng_sp80090b_health_enabled(void)
> +{
> +	struct lrng_health *health = &lrng_health;
> +
> +	return lrng_sp80090b_health_requested() && health->health_test_enabled;
> +}
> +
> +/***************************************************************************
> + * SP800-90B Compliance
> + *
> + * If the Linux-RNG is booted into FIPS mode, the following interfaces
> + * provide an SP800-90B compliant noise source:
> + *
> + * * /dev/random
> + * * getrandom(2)
> + * * get_random_bytes when using it in conjunction with
> + *   add_random_ready_callback
> + *
> + * All other interfaces, including /dev/urandom or get_random_bytes without
> + * the add_random_ready_callback cannot claim to use an SP800-90B compliant
> + * noise source.
> + ***************************************************************************/
> +
> +/**
> + * Perform SP800-90B startup testing
> + */
> +static inline void lrng_sp80090b_startup(struct lrng_health *health)
> +{
> +	if (!health->sp80090b_startup_done &&
> +	    atomic_dec_and_test(&health->sp80090b_startup_blocks)) {
> +		health->sp80090b_startup_done = true;
> +		pr_info("SP800-90B startup health tests completed\n");
> +		lrng_init_ops(0);
> +
> +		/*
> +		 * Force a reseed of secondary DRNGs to ensure they are
> +		 * seeded with entropy that passed the SP800-90B health tests.
> +		 * As the primary DRNG always will reseed before generating
> +		 * random numbers, it does not need a reseed trigger.
> +		 */
> +		lrng_sdrng_force_reseed();
> +	}
> +}
> +
> +/**
> + * Handle failure of SP800-90B startup testing
> + */
> +static inline void lrng_sp80090b_startup_failure(struct lrng_health *health)
> +{
> +	/* Reset of LRNG and its entropy - NOTE: we are in atomic context */
> +	lrng_reset();
> +
> +	/*
> +	 * Reset the SP800-90B startup test.
> +	 *
> +	 * NOTE SP800-90B section 4.3 bullet 4 does not specify what
> +	 * exactly is to be done in case of failure! Thus, we do what
> +	 * makes sense, i.e. restarting the health test and thus gating
> +	 * the output function of /dev/random and getrandom(2).
> +	 */
> +	atomic_set(&health->sp80090b_startup_blocks,
> +		   LRNG_SP80090B_STARTUP_BLOCKS);
> +}
> +
> +/**
> + * Handle failure of SP800-90B runtime testing
> + */
> +static inline void lrng_sp80090b_runtime_failure(struct lrng_health *health)
> +{
> +	lrng_sp80090b_startup_failure(health);
> +	health->sp80090b_startup_done = false;
> +}
> +
> +static inline void lrng_sp80090b_failure(struct lrng_health *health)
> +{
> +	if (health->sp80090b_startup_done) {
> +		pr_err("SP800-90B runtime health test failure - invalidating "
> +		       "all existing entropy and initiate SP800-90B startup\n");
> +		lrng_sp80090b_runtime_failure(health);
> +	} else {
> +		pr_err("SP800-90B startup test failure - resetting\n");
> +		lrng_sp80090b_startup_failure(health);
> +	}
> +}
> +
> +/**
> + * Is the SP800-90B startup testing complete?
> + *
> + * This function is called by the LRNG to determine whether to unblock
> + * a certain user interface. Therefore, only the potentially blocking
> + * user interfaces are considered SP800-90B compliant.
> + */
> +bool lrng_sp80090b_startup_complete(void)
> +{
> +	struct lrng_health *health = &lrng_health;
> +
> +	return (lrng_sp80090b_health_enabled()) ? health->sp80090b_startup_done:
> +						  true;
> +}
> +
> +bool lrng_sp80090b_compliant(void)
> +{
> +	struct lrng_health *health = &lrng_health;
> +
> +	return lrng_sp80090b_health_enabled() && health->sp80090b_startup_done;
> +}
> +
> +/***************************************************************************
> + * Adaptive Proportion Test
> + *
> + * This test complies with SP800-90B section 4.4.2.
> + ***************************************************************************/
> +
> +/**
> + * Reset the APT counter
> + *
> + * @health [in] Reference to health state
> + */
> +static inline void lrng_apt_reset(struct lrng_health *health,
> +				  unsigned int time_masked)
> +{
> +	struct lrng_apt *apt = &health->apt;
> +
> +	pr_debug("APT value %d for base %d\n",
> +		 atomic_read(&apt->apt_count), atomic_read(&apt->apt_base));
> +
> +	/* Reset APT */
> +	atomic_set(&apt->apt_count, 0);
> +	atomic_set(&apt->apt_base, time_masked);
> +}
> +
> +static inline void lrng_apt_restart(struct lrng_health *health)
> +{
> +	struct lrng_apt *apt = &health->apt;
> +
> +	atomic_set(&apt->apt_trigger, LRNG_APT_WINDOW_SIZE);
> +}
> +
> +/**
> + * Insert a new entropy event into APT
> + *
> + * This function does is void as it does not decide about the fate of a time
> + * stamp. An APT failure can only happen at the same time of a stuck test
> + * failure. Thus, the stuck failure will already decide how the time stamp
> + * is handled.
> + *
> + * @health [in] Reference to health state
> + * @now_time [in] Time stamp to process
> + */
> +static inline void lrng_apt_insert(struct lrng_health *health,
> +				   unsigned int now_time)
> +{
> +	struct lrng_apt *apt = &health->apt;
> +
> +	if (!lrng_sp80090b_health_requested())
> +		return;
> +
> +	now_time &= LRNG_APT_WORD_MASK;
> +
> +	/* Initialization of APT */
> +	if (!apt->apt_base_set) {
> +		atomic_set(&apt->apt_base, now_time);
> +		apt->apt_base_set = true;
> +		return;
> +	}
> +
> +	if (now_time == (unsigned int)atomic_read(&apt->apt_base)) {
> +		u32 apt_val = (u32)atomic_inc_return_relaxed(&apt->apt_count);
> +
> +		if (apt_val >= LRNG_APT_CUTOFF)
> +			lrng_sp80090b_failure(health);
> +	}
> +
> +	if (atomic_dec_and_test(&apt->apt_trigger)) {
> +		lrng_apt_restart(health);
> +		lrng_apt_reset(health, now_time);
> +		lrng_sp80090b_startup(health);
> +	}
> +}
> +
> +/***************************************************************************
> + * Repetition Count Test
> + *
> + * The LRNG uses an enhanced version of the Repetition Count Test
> + * (RCT) specified in SP800-90B section 4.4.1. Instead of counting identical
> + * back-to-back values, the input to the RCT is the counting of the stuck
> + * values while filling the entropy pool.
> + *
> + * The RCT is applied with an alpha of 2^-30 compliant to FIPS 140-2 IG 9.8.
> + *
> + * During the counting operation, the LRNG always calculates the RCT
> + * cut-off value of C. If that value exceeds the allowed cut-off value,
> + * the LRNG will invalidate all entropy for the entropy pool which implies
> + * that no data can be extracted from the entropy pool unless new entropy
> + * is received.
> + ***************************************************************************/
> +
> +/**
> + * Hot code path - Insert data for Repetition Count Test
> + *
> + * @health: Reference to health information
> + * @stuck: Decision of stuck test
> + */
> +static inline void lrng_rct(struct lrng_health *health, int stuck)
> +{
> +	struct lrng_rct *rct = &health->rct;
> +
> +	if (!lrng_sp80090b_health_requested())
> +		return;
> +
> +	if (stuck) {
> +		u32 rct_count = atomic_add_return_relaxed(1, &rct->rct_count);
> +
> +		pr_debug("RCT count: %u\n", rct_count);
> +
> +		/*
> +		 * The cutoff value is based on the following consideration:
> +		 * alpha = 2^-30 as recommended in FIPS 140-2 IG 9.8.
> +		 * In addition, we imply an entropy value H of 1 bit as this
> +		 * is the minimum entropy required to provide full entropy.
> +		 *
> +		 * Note, rct_count (which equals to value B in the
> +		 * pseudo code of SP800-90B section 4.4.1) starts with zero.
> +		 * Hence we need to subtract one from the cutoff value as
> +		 * calculated following SP800-90B.
> +		 */
> +		if (rct_count >= 30) {
> +			atomic_set(&rct->rct_count, 0);
> +
> +			/*
> +			 * APT must start anew as we consider all previously
> +			 * recorded data to contain no entropy.
> +			 */
> +			lrng_apt_restart(health);
> +
> +			lrng_sp80090b_failure(health);
> +		}
> +	} else {
> +		atomic_set(&rct->rct_count, 0);
> +	}
> +}
> +
> +/***************************************************************************
> + * Stuck Test
> + *
> + * Checking the:
> + *      1st derivative of the event occurrence (time delta)
> + *      2nd derivative of the event occurrence (delta of time deltas)
> + *      3rd derivative of the event occurrence (delta of delta of time deltas)
> + *
> + * All values must always be non-zero. The stuck test is only valid disabled if
> + * high-resolution time stamps are identified after initialization.
> + ***************************************************************************/
> +
> +static inline u32 lrng_delta(u32 prev, u32 next)
> +{
> +	/*
> +	 * Note that this (unsigned) subtraction does yield the correct value
> +	 * in the wraparound-case, i.e. when next < prev.
> +	 */
> +	return (next - prev);
> +}
> +
> +/**
> + * Hot code path
> + *
> + * @health: Reference to health information
> + * @now: Event time
> + * @return: 0 event occurrence not stuck (good time stamp)
> + *	    != 0 event occurrence stuck (reject time stamp)
> + */
> +static inline int lrng_irq_stuck(struct lrng_stuck_test *stuck, u32 now_time)
> +{
> +	u32 delta = lrng_delta(stuck->last_time, now_time);
> +	u32 delta2 = lrng_delta(stuck->last_delta, delta);
> +	u32 delta3 = lrng_delta(stuck->last_delta2, delta2);
> +
> +	stuck->last_time = now_time;
> +	stuck->last_delta = delta;
> +	stuck->last_delta2 = delta2;
> +
> +	if (!delta || !delta2 || !delta3)
> +		return 1;
> +
> +	return 0;
> +}
> +
> +/***************************************************************************
> + * Health test interfaces
> + ***************************************************************************/
> +
> +/**
> + * Disable all health tests
> + */
> +void lrng_health_disable(void)
> +{
> +	struct lrng_health *health = &lrng_health;
> +
> +	health->health_test_enabled = false;
> +
> +	if (lrng_sp80090b_health_requested())
> +		pr_warn("SP800-90B compliance requested but the Linux RNG is "
> +			"NOT SP800-90B compliant\n");
> +}
> +
> +/**
> + * Hot code path - Perform health test on time stamp received from an event
> + *
> + * @now_time Time stap
> + */
> +enum lrng_health_res lrng_health_test(u32 now_time)
> +{
> +	struct lrng_health *health = &lrng_health;
> +	struct lrng_stuck_test *stuck_test = this_cpu_ptr(&lrng_stuck_test);
> +	int stuck;
> +
> +	if (!health->health_test_enabled)
> +		return lrng_health_pass;
> +
> +	lrng_apt_insert(health, now_time);
> +
> +	stuck = lrng_irq_stuck(stuck_test, now_time);
> +	lrng_rct(health, stuck);
> +	if (stuck) {
> +		/* SP800-90B disallows using a failing health test time stamp */
> +		return lrng_sp80090b_health_requested() ?
> +			lrng_health_fail_drop : lrng_health_fail_use;
> +	}
> +
> +	return lrng_health_pass;
> +}
> 


-- 
Alexander E. Patrakov


[-- Attachment #2: Криптографическая подпись S/MIME --]
[-- Type: application/pkcs7-signature, Size: 4052 bytes --]

^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v24 12/12] LRNG - add interface for gathering of raw entropy
  2019-11-11 18:26 ` [PATCH v24 12/12] LRNG - add interface for gathering of raw entropy Stephan Müller
@ 2019-11-12 20:55   ` kbuild test robot
  2019-11-12 23:13     ` Stephan Müller
  0 siblings, 1 reply; 162+ messages in thread
From: kbuild test robot @ 2019-11-12 20:55 UTC (permalink / raw)
  To: Stephan Müller
  Cc: kbuild-all, Arnd Bergmann, Greg Kroah-Hartman, linux-crypto,
	LKML, linux-api, Eric W. Biederman, Alexander E. Patrakov,
	Ahmed S. Darwish, Theodore Y. Ts'o, Willy Tarreau,
	Matthew Garrett, Vito Caputo, Andreas Dilger, Jan Kara,
	Ray Strode, William Jon McCann, zhangjs, Andy Lutomirski,
	Florian Weimer, Lennart Poettering, Nicolai Stange, Peter,
	Matthias, Marcelo Henrique Cerri, Roman Drahtmueller,
	Neil Horman

[-- Attachment #1: Type: text/plain, Size: 2714 bytes --]

Hi "Stephan,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on char-misc/char-misc-testing]
[also build test WARNING on v5.4-rc7 next-20191111]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]

url:    https://github.com/0day-ci/linux/commits/Stephan-M-ller/dev-random-a-new-approach-with-full-SP800-90B-compliance/20191113-040847
base:   https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git 01b59c763fe2de845b65900485b141fdd7bbf93e
config: sh-allmodconfig (attached as .config)
compiler: sh4-linux-gcc (GCC) 7.4.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        GCC_VERSION=7.4.0 make.cross ARCH=sh 

If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

   drivers/char/lrng/lrng_testing.c: In function 'lrng_raw_extract_user':
>> drivers/char/lrng/lrng_testing.c:237:1: warning: the frame size of 1076 bytes is larger than 1024 bytes [-Wframe-larger-than=]
    }
    ^

vim +237 drivers/char/lrng/lrng_testing.c

   196	
   197	/**************************************************************************
   198	 * Debugfs interface
   199	 **************************************************************************/
   200	static int lrng_raw_extract_user(void __user *buf, size_t nbytes)
   201	{
   202		u8 tmp[LRNG_TESTING_RINGBUFFER_SIZE] __aligned(sizeof(u32));
   203		int ret = 0, large_request = (nbytes > 256);
   204	
   205		while (nbytes) {
   206			int i;
   207	
   208			if (large_request && need_resched()) {
   209				if (signal_pending(current)) {
   210					if (ret == 0)
   211						ret = -ERESTARTSYS;
   212					break;
   213				}
   214				schedule();
   215			}
   216	
   217			i = min_t(int, nbytes, sizeof(tmp));
   218			i = lrng_raw_entropy_reader(tmp, i);
   219			if (i <= 0) {
   220				if (i < 0)
   221					ret = i;
   222				break;
   223			}
   224			if (copy_to_user(buf, tmp, i)) {
   225				ret = -EFAULT;
   226				break;
   227			}
   228	
   229			nbytes -= i;
   230			buf = (u8 *)buf + i;
   231			ret += i;
   232		}
   233	
   234		memzero_explicit(tmp, sizeof(tmp));
   235	
   236		return ret;
 > 237	}
   238	

---
0-DAY kernel test infrastructure                 Open Source Technology Center
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 52299 bytes --]

^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v24 01/12] Linux Random Number Generator
  2019-11-11 18:18 ` [PATCH v24 01/12] Linux Random Number Generator Stephan Müller
  2019-11-11 23:54   ` Thomas Gleixner
@ 2019-11-12 22:30   ` kbuild test robot
  2019-11-12 23:15     ` Stephan Müller
  2019-11-13  0:14   ` kbuild test robot
  2019-11-24  4:51   ` Sandy Harris
  3 siblings, 1 reply; 162+ messages in thread
From: kbuild test robot @ 2019-11-12 22:30 UTC (permalink / raw)
  To: Stephan Müller
  Cc: kbuild-all, Arnd Bergmann, Greg Kroah-Hartman, linux-crypto,
	LKML, linux-api, Eric W. Biederman, Alexander E. Patrakov,
	Ahmed S. Darwish, Theodore Y. Ts'o, Willy Tarreau,
	Matthew Garrett, Vito Caputo, Andreas Dilger, Jan Kara,
	Ray Strode, William Jon McCann, zhangjs, Andy Lutomirski,
	Florian Weimer, Lennart Poettering, Nicolai Stange, Peter,
	Matthias, Marcelo Henrique Cerri, Roman Drahtmueller,
	Neil Horman

[-- Attachment #1: Type: text/plain, Size: 2013 bytes --]

Hi "Stephan,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on char-misc/char-misc-testing]
[also build test ERROR on v5.4-rc7 next-20191112]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]

url:    https://github.com/0day-ci/linux/commits/Stephan-M-ller/dev-random-a-new-approach-with-full-SP800-90B-compliance/20191113-040847
base:   https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git 01b59c763fe2de845b65900485b141fdd7bbf93e
config: i386-randconfig-f003-201945 (attached as .config)
compiler: gcc-7 (Debian 7.4.0-14) 7.4.0
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   In file included from <command-line>:0:0:
   include/linux/lrng.h: In function 'lrng_set_drng_cb':
>> include/linux/lrng.h:80:61: error: 'EOPNOTSUPP' undeclared (first use in this function)
    lrng_set_drng_cb(const struct lrng_crypto_cb *cb) { return -EOPNOTSUPP; }
                                                                ^~~~~~~~~~
   include/linux/lrng.h:80:61: note: each undeclared identifier is reported only once for each function it appears in

vim +/EOPNOTSUPP +80 include/linux/lrng.h

    74	
    75	/* Register cryptographic backend */
    76	#ifdef CONFIG_LRNG_DRNG_SWITCH
    77	int lrng_set_drng_cb(const struct lrng_crypto_cb *cb);
    78	#else	/* CONFIG_LRNG_DRNG_SWITCH */
    79	static inline int
  > 80	lrng_set_drng_cb(const struct lrng_crypto_cb *cb) { return -EOPNOTSUPP; }
    81	#endif	/* CONFIG_LRNG_DRNG_SWITCH */
    82	

---
0-DAY kernel test infrastructure                 Open Source Technology Center
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 32056 bytes --]

^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v24 00/12] /dev/random - a new approach with full SP800-90B compliance
  2019-11-12 13:23 ` [PATCH v24 00/12] /dev/random - a new approach with full SP800-90B compliance Florian Weimer
@ 2019-11-12 22:43   ` Stephan Müller
  0 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-12 22:43 UTC (permalink / raw)
  To: Florian Weimer
  Cc: Arnd Bergmann, Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

Am Dienstag, 12. November 2019, 14:23:10 CET schrieb Florian Weimer:

Hi Florian,

> * Stephan Müller:
> > * support deactivation of TRNG (i.e. blocking behavior of /dev/random)
> > 
> >   at compile time. If deactivated, /dev/random behaves like
> >   getrandom(2).
> 
> I don't quite understand this comment.  Doesn't getrandom with the
> GRND_RANDOM always behave like /dev/random?  Presumably, without the
> TRNG tap, the GRND_RANDOM flag for getrandom is ignored, and reading
> from /dev/random behaves like reading from /dev/urandom.

Absolutely. Apologies for the imprecision here. I will correct that.

The idea is that the constant blocking behavior of /dev/random and GRND_RANDOM 
is replaced with the blocking behavior of getrandom(2) without the GRND_RANDOM 
flag (i.e. the interface waits until the LRNG thinks it is completely seeded 
before it provides ulimited data).
> 
> Anyway, reading the accompanying PDF, this looks rather impressive:
> the userspace bootstrapping problem is gone (the issue where waiting
> for more entropy prevents the collection of more entropy), *and* we
> can still make the standards people happy.
> 
> (Replying from my other account due to mail issues, sorry.)


Ciao
Stephan



^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v24 00/12] /dev/random - a new approach with full SP800-90B compliance
  2019-11-12 15:33 ` Andy Lutomirski
@ 2019-11-12 23:03   ` Stephan Müller
  2019-11-12 23:26     ` Stephan Müller
  2019-11-13  4:24   ` Stephan Müller
  1 sibling, 1 reply; 162+ messages in thread
From: Stephan Müller @ 2019-11-12 23:03 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Arnd Bergmann, Greg Kroah-Hartman, Linux Crypto Mailing List,
	LKML, Linux API, Eric W. Biederman, Alexander E. Patrakov,
	Ahmed S. Darwish, Theodore Y. Ts'o, Willy Tarreau,
	Matthew Garrett, Vito Caputo, Andreas Dilger, Jan Kara,
	Ray Strode, William Jon McCann, zhangjs, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

Am Dienstag, 12. November 2019, 16:33:59 CET schrieb Andy Lutomirski:

Hi Andy,

> On Mon, Nov 11, 2019 at 11:13 AM Stephan Müller <smueller@chronox.de> wrote:
> > The following patch set provides a different approach to /dev/random which
> > is called Linux Random Number Generator (LRNG) to collect entropy within
> > the Linux kernel. The main improvements compared to the existing
> > /dev/random is to provide sufficient entropy during boot time as well as
> > in virtual environments and when using SSDs. A secondary design goal is
> > to limit the impact of the entropy collection on massive parallel systems
> > and also allow the use accelerated cryptographic primitives. Also, all
> > steps of the entropic data processing are testable.
> 
> This is very nice!
> 
> > The LRNG patch set allows a user to select use of the existing /dev/random
> > or the LRNG during compile time. As the LRNG provides API and ABI
> > compatible interfaces to the existing /dev/random implementation, the
> > user can freely chose the RNG implementation without affecting kernel or
> > user space operations.
> > 
> > This patch set provides early boot-time entropy which implies that no
> > additional flags to the getrandom(2) system call discussed recently on
> > the LKML is considered to be necessary.
> 
> I'm uneasy about this.  I fully believe that, *on x86*, this works.
> But on embedded systems with in-order CPUs, a single clock, and very
> lightweight boot processes, most or all of boot might be too
> deterministic for this to work.

I agree that in such cases, my LRNG getrandom(2) would also block until the 
LRNG thinks it collected 256 bits of entropy. However, I am under the 
impression that the LRNG collects that entropy faster that the existing /dev/
random implementation, even in this case.

Nicolai is copied on this thread. He promised to have the LRNG tested on such 
a minimalistic system that you describe. I hope he could contribute some 
numbers from that test helping us to understand how much of a problem we face.
> 
> I have a somewhat competing patch set here:
> 
> https://git.kernel.org/pub/scm/linux/kernel/git/luto/linux.git/log/?h=random
> /kill-it
> 
> (Ignore the "horrible test hack" and the debugfs part.)
> 
> The basic summary is that I change /dev/random so that it becomes
> functionally identical to getrandom(..., 0) -- in other words, it
> blocks until the CRNG is initialized but is then identical to
> /dev/urandom.

This would be equal to the LRNG code without compiling the TRNG.

> And I add getrandom(...., GRND_INSECURE) that is
> functionally identical to the existing /dev/urandom: it always returns
> *something* immediately, but it may or may not actually be
> cryptographically random or even random at all depending on system
> details.

Ok, if it is suggested that getrandom(2) should also have a mode to behave 
exactly like /dev/urandom by not waiting until it is fully seeded, I am happy 
to add that.
> 
> In other words, my series simplifies the ABI that we support.  Right
> now, we have three ways to ask for random numbers with different
> semantics and we need to have to RNGs in the kernel at all time.  With
> my changes, we have only two ways to ask for random numbers, and the
> /dev/random pool is entirely gone.

Again, I do not want to stand in the way of changing the ABI if this is the 
agreed way. All I want to say is that the LRNG seemingly is initialized much 
faster than the existing /dev/random. If this is not fast enough for some 
embedded environments, I would not want to stand in the way to make their life 
easier.
> 
> Would you be amenable to merging this into your series (i.e. either
> merging the code or just the ideas)? 

Absolutely. I would be happy to do that.

Allow me to pull your code (I am currently behind a slow line) and review it 
to see how best to integrate it.

> This would let you get rid of
> things like the compile-time selection of the blocking TRNG, since the
> blocking TRNG would be entirely gone.

Hm, I am not so sure we should do that.

Allow me to explain: I am also collaborating on the European side with the 
German BSI. They love /dev/random as it is a "NTG.1" RNG based on their AIS 31 
standard.

In order to seed a deterministic RNG (like OpenSSL, GnuTLS, etc. which are all 
defined to be "DRG.3" or "DRG.2"), BSI mandates that the seed source is an 
NTG.1.

By getting rid of the TRNG entirely and having /dev/random entirely behaving 
like /dev/urandom or getrandom(2) without the GRND_RANDOM flag, the kernel 
would "only" provide a "DRG.3" type RNG. This type of RNG would be disallowed 
to seed another "DRG.3" or "DRG.2".

In plain English that means that for BSI's requirements, if the TRNG is gone 
there would be no native seed source on Linux any more that can satisfy the 
requirement. This is the ultimate reason why I made the TRNG compile-time 
selectable: to support embedded systems but also support use cases like the 
BSI case.

Please consider that I maintain a study over the last years for BSI trying to 
ensure that the NTG.1 property is always met [1] [2]. The sole purpose of that 
study is around this NTG.1.
> 
> Or do you think that a kernel-provided blocking TRNG is a genuinely
> useful thing to keep around?

Yes, as I hope I explained it appropriately above, there are standardization 
requirements that need the TRNG.

PS: When I was forwarding Linus' email on eliminating the blocking_pool to 
BSI, I saw unhappy faces. :-)

I would like to help both sides here.

[1] https://www.bsi.bund.de/SharedDocs/Downloads/EN/BSI/Publications/Studies/
LinuxRNG/NTG1_Kerneltabelle_EN.pdf?__blob=publicationFile&v=3

[2] https://www.bsi.bund.de/SharedDocs/Downloads/EN/BSI/Publications/Studies/
LinuxRNG/NTG1_Kerneltabelle_EN.pdf?__blob=publicationFile&v=3

Ciao
Stephan



^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v24 11/12] LRNG - add SP800-90B compliant health tests
  2019-11-12 19:58   ` Alexander E. Patrakov
@ 2019-11-12 23:11     ` Stephan Müller
  2019-11-13  0:36     ` Stephan Müller
  1 sibling, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-12 23:11 UTC (permalink / raw)
  To: Alexander E. Patrakov
  Cc: Arnd Bergmann, Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Ahmed S. Darwish, Theodore Y. Ts'o,
	Willy Tarreau, Matthew Garrett, Vito Caputo, Andreas Dilger,
	Jan Kara, Ray Strode, William Jon McCann, zhangjs,
	Andy Lutomirski, Florian Weimer, Lennart Poettering,
	Nicolai Stange, Peter, Matthias, Marcelo Henrique Cerri,
	Roman Drahtmueller, Neil Horman

Am Dienstag, 12. November 2019, 20:58:32 CET schrieb Alexander E. Patrakov:

Hi Alexander,

> 11.11.2019 23:26, Stephan Müller пишет:
> > Implement health tests for LRNG's slow noise sources as mandated by
> > SP-800-90B The file contains the following health tests:
> > 
> > - stuck test: The stuck test calculates the first, second and third
> > 
> >    discrete derivative of the time stamp to be processed by the LFSR.
> >    Only if all three values are zero, the received time delta is
> >    considered to be non-stuck.
> 
> The other way round?

Opps, yes, of course. If all three a non-zero...

Fixed.
> 
> > - SP800-90B Repetition Count Test (RCT): The LRNG uses an enhanced
> > 
> >    version of the RCT specified in SP800-90B section 4.4.1. Instead of
> >    counting identical back-to-back values, the input to the RCT is the
> >    counting of the stuck values during the processing of received
> >    interrupt events. The RCT is applied with alpha=2^-30 compliant to
> >    the recommendation of FIPS 140-2 IG 9.8. During the counting operation,
> >    the LRNG always calculates the RCT cut-off value of C. If that value
> >    exceeds the allowed cut-off value, the LRNG will trigger the health
> >    test failure discussed below. An error is logged to the kernel log
> >    that such RCT failure occurred. This test is only applied and
> >    enforced in FIPS mode, i.e. when the kernel compiled with
> >    CONFIG_CONFIG_FIPS is started with fips=1.
> > 
> > - SP800-90B Adaptive Proportion Test (APT): The LRNG implements the
> > 
> >    APT as defined in SP800-90B section 4.4.2. The assumed
> 
> The sentence ends in the middle.

Fixed:

"""
SP800-90B Adaptive Proportion Test (APT): The LRNG implements the
  APT as defined in SP800-90B section 4.4.2. The applied significance
  level again is alpha=2^-30 compliant to the recommendation of FIPS 
  140-2 IG 9.8.
"""

> 
> > The aforementioned health tests are applied to the first 1,024 time stamps
> > obtained from interrupt events. In case one error is identified for either
> > the RCT, or the APT, the collected entropy is invalidated and the
> > SP800-90B startup health test is restarted.
> > 
> > As long as the SP800-90B startup health test is not completed, all LRNG
> > random number output interfaces that may block will block and not generate
> > any data. This implies that only those potentially blocking interfaces are
> > defined to provide random numbers that are seeded with the interrupt noise
> > source being SP800-90B compliant. All other output interfaces will not be
> > affected by the SP800-90B startup test and thus are not considered
> > SP800-90B compliant.
> > 
> > At runtime, the SP800-90B APT and RCT are applied to each time stamp
> > generated for a received interrupt. When either the APT and RCT indicates
> > a noise source failure, the LRNG is reset to a state it has immediately
> > after boot:
> > 
> > - all entropy counters are set to zero
> > 
> > - the SP800-90B startup tests are re-performed which implies that
> > getrandom(2) would block again until new entropy was collected
> > 
> > To summarize, the following rules apply:
> > 
> > • SP800-90B compliant output interfaces
> > 
> >    - /dev/random
> >    
> >    - getrandom(2) system call
> >    
> >    -  get_random_bytes kernel-internal interface when being triggered by
> >    
> >       the callback registered with add_random_ready_callback
> > 
> > • SP800-90B non-compliant output interfaces
> > 
> >    - /dev/urandom
> >    
> >    - get_random_bytes kernel-internal interface called directly
> >    
> >    - randomize_page kernel-internal interface
> >    
> >    - get_random_u32 and get_random_u64 kernel-internal interfaces
> >    
> >    - get_random_u32_wait, get_random_u64_wait, get_random_int_wait, and
> >    
> >      get_random_long_wait kernel-internal interfaces
> > 
> > If either the RCT, or the APT health test fails irrespective whether
> > 
> > during initialization or runtime, the following actions occur:
> >    1. The entropy of the entire entropy pool is invalidated.
> >    
> >    2. The primary and all secondary DRNGs are reset which imply that they
> >    
> >       are treated as being not seeded and require a reseed during next
> >       invocation.
> >    
> >    3. The SP800-90B startup health test are initiated with all
> >    
> >       implications of the startup tests. That implies that from that point
> >       on, new events must be observed and its entropy must be inserted
> >       into
> >       the entropy pool before random numbers are calculated from the
> >       entropy pool.
> > 
> > Further details on the SP800-90B compliance and the availability of all
> > test tools required to perform all tests mandated by SP800-90B are
> > provided at [1].
> > 
> > The entire health testing code is compile-time configurable.
> > 
> > CC: "Eric W. Biederman" <ebiederm@xmission.com>
> > CC: "Alexander E. Patrakov" <patrakov@gmail.com>
> > CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
> > CC: "Theodore Y. Ts'o" <tytso@mit.edu>
> > CC: Willy Tarreau <w@1wt.eu>
> > CC: Matthew Garrett <mjg59@srcf.ucam.org>
> > CC: Vito Caputo <vcaputo@pengaru.com>
> > CC: Andreas Dilger <adilger.kernel@dilger.ca>
> > CC: Jan Kara <jack@suse.cz>
> > CC: Ray Strode <rstrode@redhat.com>
> > CC: William Jon McCann <mccann@jhu.edu>
> > CC: zhangjs <zachary@baishancloud.com>
> > CC: Andy Lutomirski <luto@kernel.org>
> > CC: Florian Weimer <fweimer@redhat.com>
> > CC: Lennart Poettering <mzxreary@0pointer.de>
> > CC: Nicolai Stange <nstange@suse.de>
> > Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
> > Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
> > Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
> > Tested-by: Neil Horman <nhorman@redhat.com>
> > Signed-off-by: Stephan Mueller <smueller@chronox.de>
> > ---
> > 
> >   drivers/char/lrng/Kconfig       |  13 +
> >   drivers/char/lrng/Makefile      |   1 +
> >   drivers/char/lrng/lrng_health.c | 424 ++++++++++++++++++++++++++++++++
> >   3 files changed, 438 insertions(+)
> >   create mode 100644 drivers/char/lrng/lrng_health.c
> > 
> > diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
> > index efc5f9aaa2a3..4373a1a19538 100644
> > --- a/drivers/char/lrng/Kconfig
> > +++ b/drivers/char/lrng/Kconfig
> > @@ -113,4 +113,17 @@ config LRNG_TRNG_SUPPORT
> > 
> >   	  With the TRNG support the /dev/random device will block
> >   	  if insufficient entropy is available.
> > 
> > +config LRNG_HEALTH_TESTS
> > +	bool "Enable noise source online health tests"
> > +	help
> > +	  The online health tests validate the noise source at
> > +	  runtime for fatal errors. These tests include SP800-90B
> > +	  compliant tests which are invoked if the system is booted
> > +	  with fips=1. In case of fatal errors during active
> > +	  SP800-90B tests, the issue is logged and the noise
> > +	  data is discarded. These tests are required for full
> > +	  compliance with SP800-90B.
> 
> How have you tested that these tests work at runtime? Maybe add some
> code under a new CONFIG item that depends on CONFIG_BROKEN that
> deliberately botches the RNG and triggers failures?

I manually broke it for testing as follows: I set the LRNG_APT_CUTOFF to 1 to 
trigger the APT failure and I changed the line 

if (rct_count >= 30) {

to 

if (rct_count >= 1) {

which effectively sets the RCT cutoff value to 1.

Allow me to check how CONFIG_BROKEN really works to see how I can roll this 
test into CONFIG_BROKEN.

Thank you very much for your review.


> 
> > +
> > +	  If unsure, say Y.
> > +
> > 
> >   endif # LRNG
> > 
> > diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
> > index 1c72bc060bce..0713e9c0aa6e 100644
> > --- a/drivers/char/lrng/Makefile
> > +++ b/drivers/char/lrng/Makefile
> > @@ -15,3 +15,4 @@ obj-$(CONFIG_LRNG_DRBG)		+= lrng_drbg.o
> > 
> >   obj-$(CONFIG_LRNG_KCAPI)	+= lrng_kcapi.o
> >   obj-$(CONFIG_LRNG_JENT)		+= lrng_jent.o
> >   obj-$(CONFIG_LRNG_TRNG_SUPPORT)	+= lrng_trng.o
> > 
> > +obj-$(CONFIG_LRNG_HEALTH_TESTS)	+= lrng_health.o
> > diff --git a/drivers/char/lrng/lrng_health.c
> > b/drivers/char/lrng/lrng_health.c new file mode 100644
> > index 000000000000..b8d96cec1f71
> > --- /dev/null
> > +++ b/drivers/char/lrng/lrng_health.c
> > @@ -0,0 +1,424 @@
> > +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
> > +/*
> > + * Linux Random Number Generator (LRNG) Health Testing
> > + *
> > + * Copyright (C) 2019, Stephan Mueller <smueller@chronox.de>
> > + *
> > + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
> > + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
> > + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
> > + * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
> > + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> > + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
> > + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
> > + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
> > + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> > + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
> > + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
> > + * DAMAGE.
> > + */
> > +
> > +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> > +
> > +#include <linux/fips.h>
> > +#include <linux/module.h>
> > +
> > +#include "lrng_internal.h"
> > +
> > +/* Stuck Test */
> > +struct lrng_stuck_test {
> > +	u32 last_time;		/* Stuck test: time of previous IRQ */
> > +	u32 last_delta;		/* Stuck test: delta of previous IRQ */
> > +	u32 last_delta2;	/* Stuck test: 2. time derivation of prev IRQ */
> > +};
> > +
> > +/* Repetition Count Test */
> > +struct lrng_rct {
> > +	atomic_t rct_count;	/* Number of stuck values */
> > +};
> > +
> > +/* Adaptive Proportion Test */
> > +struct lrng_apt {
> > +	/* Taken from SP800-90B sec 4.4.2 - significance level 2^-30 */
> > +#define LRNG_APT_CUTOFF		325
> > +	/* Data window size */
> > +#define LRNG_APT_WINDOW_SIZE	512
> > +	/* LSB of time stamp to process */
> > +#define LRNG_APT_LSB		16
> > +#define LRNG_APT_WORD_MASK	(LRNG_APT_LSB - 1)
> > +	atomic_t apt_count;		/* APT counter */
> > +	atomic_t apt_base;		/* APT base reference */
> > +
> > +	atomic_t apt_trigger;
> > +	bool apt_base_set;	/* Is APT base set? */
> > +};
> > +
> > +/* The health test code must operate lock-less */
> > +struct lrng_health {
> > +	struct lrng_rct rct;
> > +	struct lrng_apt apt;
> > +
> > +	bool health_test_enabled;
> > +
> > +	/* SP800-90B startup health tests */
> > +#define LRNG_SP80090B_STARTUP_SAMPLES  1024
> > +#define LRNG_SP80090B_STARTUP_BLOCKS   ((LRNG_SP80090B_STARTUP_SAMPLES +
> > \
> > +					 LRNG_APT_WINDOW_SIZE - 1) /    \
> > +					LRNG_APT_WINDOW_SIZE)
> > +	bool sp80090b_startup_done;
> > +	atomic_t sp80090b_startup_blocks;
> > +};
> > +
> > +static struct lrng_health lrng_health = {
> > +	.rct.rct_count = ATOMIC_INIT(0),
> > +
> > +	.apt.apt_count = ATOMIC_INIT(0),
> > +	.apt.apt_base = ATOMIC_INIT(-1),
> > +	.apt.apt_trigger = ATOMIC_INIT(LRNG_APT_WINDOW_SIZE),
> > +	.apt.apt_base_set = false,
> > +
> > +	.health_test_enabled = true,
> > +
> > +	.sp80090b_startup_blocks = ATOMIC_INIT(LRNG_SP80090B_STARTUP_BLOCKS),
> > +	.sp80090b_startup_done = false,
> > +};
> > +
> > +static DEFINE_PER_CPU(struct lrng_stuck_test, lrng_stuck_test);
> > +
> > +static inline bool lrng_sp80090b_health_requested(void)
> > +{
> > +	/* Health tests are only requested in FIPS mode */
> > +	return fips_enabled;
> > +}
> > +
> > +static inline bool lrng_sp80090b_health_enabled(void)
> > +{
> > +	struct lrng_health *health = &lrng_health;
> > +
> > +	return lrng_sp80090b_health_requested() && health->health_test_enabled;
> > +}
> > +
> > +/************************************************************************
> > *** + * SP800-90B Compliance
> > + *
> > + * If the Linux-RNG is booted into FIPS mode, the following interfaces
> > + * provide an SP800-90B compliant noise source:
> > + *
> > + * * /dev/random
> > + * * getrandom(2)
> > + * * get_random_bytes when using it in conjunction with
> > + *   add_random_ready_callback
> > + *
> > + * All other interfaces, including /dev/urandom or get_random_bytes
> > without + * the add_random_ready_callback cannot claim to use an
> > SP800-90B compliant + * noise source.
> > +
> > *************************************************************************
> > **/ +
> > +/**
> > + * Perform SP800-90B startup testing
> > + */
> > +static inline void lrng_sp80090b_startup(struct lrng_health *health)
> > +{
> > +	if (!health->sp80090b_startup_done &&
> > +	    atomic_dec_and_test(&health->sp80090b_startup_blocks)) {
> > +		health->sp80090b_startup_done = true;
> > +		pr_info("SP800-90B startup health tests completed\n");
> > +		lrng_init_ops(0);
> > +
> > +		/*
> > +		 * Force a reseed of secondary DRNGs to ensure they are
> > +		 * seeded with entropy that passed the SP800-90B health tests.
> > +		 * As the primary DRNG always will reseed before generating
> > +		 * random numbers, it does not need a reseed trigger.
> > +		 */
> > +		lrng_sdrng_force_reseed();
> > +	}
> > +}
> > +
> > +/**
> > + * Handle failure of SP800-90B startup testing
> > + */
> > +static inline void lrng_sp80090b_startup_failure(struct lrng_health
> > *health) +{
> > +	/* Reset of LRNG and its entropy - NOTE: we are in atomic context */
> > +	lrng_reset();
> > +
> > +	/*
> > +	 * Reset the SP800-90B startup test.
> > +	 *
> > +	 * NOTE SP800-90B section 4.3 bullet 4 does not specify what
> > +	 * exactly is to be done in case of failure! Thus, we do what
> > +	 * makes sense, i.e. restarting the health test and thus gating
> > +	 * the output function of /dev/random and getrandom(2).
> > +	 */
> > +	atomic_set(&health->sp80090b_startup_blocks,
> > +		   LRNG_SP80090B_STARTUP_BLOCKS);
> > +}
> > +
> > +/**
> > + * Handle failure of SP800-90B runtime testing
> > + */
> > +static inline void lrng_sp80090b_runtime_failure(struct lrng_health
> > *health) +{
> > +	lrng_sp80090b_startup_failure(health);
> > +	health->sp80090b_startup_done = false;
> > +}
> > +
> > +static inline void lrng_sp80090b_failure(struct lrng_health *health)
> > +{
> > +	if (health->sp80090b_startup_done) {
> > +		pr_err("SP800-90B runtime health test failure - invalidating "
> > +		       "all existing entropy and initiate SP800-90B startup\n");
> > +		lrng_sp80090b_runtime_failure(health);
> > +	} else {
> > +		pr_err("SP800-90B startup test failure - resetting\n");
> > +		lrng_sp80090b_startup_failure(health);
> > +	}
> > +}
> > +
> > +/**
> > + * Is the SP800-90B startup testing complete?
> > + *
> > + * This function is called by the LRNG to determine whether to unblock
> > + * a certain user interface. Therefore, only the potentially blocking
> > + * user interfaces are considered SP800-90B compliant.
> > + */
> > +bool lrng_sp80090b_startup_complete(void)
> > +{
> > +	struct lrng_health *health = &lrng_health;
> > +
> > +	return (lrng_sp80090b_health_enabled()) ? health->sp80090b_startup_done:
> > +						  true;
> > +}
> > +
> > +bool lrng_sp80090b_compliant(void)
> > +{
> > +	struct lrng_health *health = &lrng_health;
> > +
> > +	return lrng_sp80090b_health_enabled() && health->sp80090b_startup_done;
> > +}
> > +
> > +/************************************************************************
> > *** + * Adaptive Proportion Test
> > + *
> > + * This test complies with SP800-90B section 4.4.2.
> > +
> > *************************************************************************
> > **/ +
> > +/**
> > + * Reset the APT counter
> > + *
> > + * @health [in] Reference to health state
> > + */
> > +static inline void lrng_apt_reset(struct lrng_health *health,
> > +				  unsigned int time_masked)
> > +{
> > +	struct lrng_apt *apt = &health->apt;
> > +
> > +	pr_debug("APT value %d for base %d\n",
> > +		 atomic_read(&apt->apt_count), atomic_read(&apt->apt_base));
> > +
> > +	/* Reset APT */
> > +	atomic_set(&apt->apt_count, 0);
> > +	atomic_set(&apt->apt_base, time_masked);
> > +}
> > +
> > +static inline void lrng_apt_restart(struct lrng_health *health)
> > +{
> > +	struct lrng_apt *apt = &health->apt;
> > +
> > +	atomic_set(&apt->apt_trigger, LRNG_APT_WINDOW_SIZE);
> > +}
> > +
> > +/**
> > + * Insert a new entropy event into APT
> > + *
> > + * This function does is void as it does not decide about the fate of a
> > time + * stamp. An APT failure can only happen at the same time of a
> > stuck test + * failure. Thus, the stuck failure will already decide how
> > the time stamp + * is handled.
> > + *
> > + * @health [in] Reference to health state
> > + * @now_time [in] Time stamp to process
> > + */
> > +static inline void lrng_apt_insert(struct lrng_health *health,
> > +				   unsigned int now_time)
> > +{
> > +	struct lrng_apt *apt = &health->apt;
> > +
> > +	if (!lrng_sp80090b_health_requested())
> > +		return;
> > +
> > +	now_time &= LRNG_APT_WORD_MASK;
> > +
> > +	/* Initialization of APT */
> > +	if (!apt->apt_base_set) {
> > +		atomic_set(&apt->apt_base, now_time);
> > +		apt->apt_base_set = true;
> > +		return;
> > +	}
> > +
> > +	if (now_time == (unsigned int)atomic_read(&apt->apt_base)) {
> > +		u32 apt_val = (u32)atomic_inc_return_relaxed(&apt->apt_count);
> > +
> > +		if (apt_val >= LRNG_APT_CUTOFF)
> > +			lrng_sp80090b_failure(health);
> > +	}
> > +
> > +	if (atomic_dec_and_test(&apt->apt_trigger)) {
> > +		lrng_apt_restart(health);
> > +		lrng_apt_reset(health, now_time);
> > +		lrng_sp80090b_startup(health);
> > +	}
> > +}
> > +
> > +/************************************************************************
> > *** + * Repetition Count Test
> > + *
> > + * The LRNG uses an enhanced version of the Repetition Count Test
> > + * (RCT) specified in SP800-90B section 4.4.1. Instead of counting
> > identical + * back-to-back values, the input to the RCT is the counting
> > of the stuck + * values while filling the entropy pool.
> > + *
> > + * The RCT is applied with an alpha of 2^-30 compliant to FIPS 140-2 IG
> > 9.8. + *
> > + * During the counting operation, the LRNG always calculates the RCT
> > + * cut-off value of C. If that value exceeds the allowed cut-off value,
> > + * the LRNG will invalidate all entropy for the entropy pool which
> > implies
> > + * that no data can be extracted from the entropy pool unless new entropy
> > + * is received.
> > +
> > *************************************************************************
> > **/ +
> > +/**
> > + * Hot code path - Insert data for Repetition Count Test
> > + *
> > + * @health: Reference to health information
> > + * @stuck: Decision of stuck test
> > + */
> > +static inline void lrng_rct(struct lrng_health *health, int stuck)
> > +{
> > +	struct lrng_rct *rct = &health->rct;
> > +
> > +	if (!lrng_sp80090b_health_requested())
> > +		return;
> > +
> > +	if (stuck) {
> > +		u32 rct_count = atomic_add_return_relaxed(1, &rct->rct_count);
> > +
> > +		pr_debug("RCT count: %u\n", rct_count);
> > +
> > +		/*
> > +		 * The cutoff value is based on the following consideration:
> > +		 * alpha = 2^-30 as recommended in FIPS 140-2 IG 9.8.
> > +		 * In addition, we imply an entropy value H of 1 bit as this
> > +		 * is the minimum entropy required to provide full entropy.
> > +		 *
> > +		 * Note, rct_count (which equals to value B in the
> > +		 * pseudo code of SP800-90B section 4.4.1) starts with zero.
> > +		 * Hence we need to subtract one from the cutoff value as
> > +		 * calculated following SP800-90B.
> > +		 */
> > +		if (rct_count >= 30) {
> > +			atomic_set(&rct->rct_count, 0);
> > +
> > +			/*
> > +			 * APT must start anew as we consider all previously
> > +			 * recorded data to contain no entropy.
> > +			 */
> > +			lrng_apt_restart(health);
> > +
> > +			lrng_sp80090b_failure(health);
> > +		}
> > +	} else {
> > +		atomic_set(&rct->rct_count, 0);
> > +	}
> > +}
> > +
> > +/************************************************************************
> > *** + * Stuck Test
> > + *
> > + * Checking the:
> > + *      1st derivative of the event occurrence (time delta)
> > + *      2nd derivative of the event occurrence (delta of time deltas)
> > + *      3rd derivative of the event occurrence (delta of delta of time
> > deltas) + *
> > + * All values must always be non-zero. The stuck test is only valid
> > disabled if + * high-resolution time stamps are identified after
> > initialization. +
> > *************************************************************************
> > **/ +
> > +static inline u32 lrng_delta(u32 prev, u32 next)
> > +{
> > +	/*
> > +	 * Note that this (unsigned) subtraction does yield the correct value
> > +	 * in the wraparound-case, i.e. when next < prev.
> > +	 */
> > +	return (next - prev);
> > +}
> > +
> > +/**
> > + * Hot code path
> > + *
> > + * @health: Reference to health information
> > + * @now: Event time
> > + * @return: 0 event occurrence not stuck (good time stamp)
> > + *	    != 0 event occurrence stuck (reject time stamp)
> > + */
> > +static inline int lrng_irq_stuck(struct lrng_stuck_test *stuck, u32
> > now_time) +{
> > +	u32 delta = lrng_delta(stuck->last_time, now_time);
> > +	u32 delta2 = lrng_delta(stuck->last_delta, delta);
> > +	u32 delta3 = lrng_delta(stuck->last_delta2, delta2);
> > +
> > +	stuck->last_time = now_time;
> > +	stuck->last_delta = delta;
> > +	stuck->last_delta2 = delta2;
> > +
> > +	if (!delta || !delta2 || !delta3)
> > +		return 1;
> > +
> > +	return 0;
> > +}
> > +
> > +/************************************************************************
> > *** + * Health test interfaces
> > +
> > *************************************************************************
> > **/ +
> > +/**
> > + * Disable all health tests
> > + */
> > +void lrng_health_disable(void)
> > +{
> > +	struct lrng_health *health = &lrng_health;
> > +
> > +	health->health_test_enabled = false;
> > +
> > +	if (lrng_sp80090b_health_requested())
> > +		pr_warn("SP800-90B compliance requested but the Linux RNG is "
> > +			"NOT SP800-90B compliant\n");
> > +}
> > +
> > +/**
> > + * Hot code path - Perform health test on time stamp received from an
> > event + *
> > + * @now_time Time stap
> > + */
> > +enum lrng_health_res lrng_health_test(u32 now_time)
> > +{
> > +	struct lrng_health *health = &lrng_health;
> > +	struct lrng_stuck_test *stuck_test = this_cpu_ptr(&lrng_stuck_test);
> > +	int stuck;
> > +
> > +	if (!health->health_test_enabled)
> > +		return lrng_health_pass;
> > +
> > +	lrng_apt_insert(health, now_time);
> > +
> > +	stuck = lrng_irq_stuck(stuck_test, now_time);
> > +	lrng_rct(health, stuck);
> > +	if (stuck) {
> > +		/* SP800-90B disallows using a failing health test time stamp */
> > +		return lrng_sp80090b_health_requested() ?
> > +			lrng_health_fail_drop : lrng_health_fail_use;
> > +	}
> > +
> > +	return lrng_health_pass;
> > +}


Ciao
Stephan



^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v24 12/12] LRNG - add interface for gathering of raw entropy
  2019-11-12 20:55   ` kbuild test robot
@ 2019-11-12 23:13     ` Stephan Müller
  0 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-12 23:13 UTC (permalink / raw)
  To: kbuild test robot
  Cc: kbuild-all, Arnd Bergmann, Greg Kroah-Hartman, linux-crypto,
	LKML, linux-api, Eric W. Biederman, Alexander E. Patrakov,
	Ahmed S. Darwish, Theodore Y. Ts'o, Willy Tarreau,
	Matthew Garrett, Vito Caputo, Andreas Dilger, Jan Kara,
	Ray Strode, William Jon McCann, zhangjs, Andy Lutomirski,
	Florian Weimer, Lennart Poettering, Nicolai Stange, Peter,
	Matthias, Marcelo Henrique Cerri, Roman Drahtmueller,
	Neil Horman

Am Dienstag, 12. November 2019, 21:55:10 CET schrieb kbuild test robot:

Hi kbuild,

> Hi "Stephan,
> 
> Thank you for the patch! Perhaps something to improve:
> 
> [auto build test WARNING on char-misc/char-misc-testing]
> [also build test WARNING on v5.4-rc7 next-20191111]
> [if your patch is applied to the wrong git tree, please drop us a note to
> help improve the system. BTW, we also suggest to use '--base' option to
> specify the base tree in git format-patch, please see
> https://stackoverflow.com/a/37406982]
> 
> url:   
> https://github.com/0day-ci/linux/commits/Stephan-M-ller/dev-random-a-new-ap
> proach-with-full-SP800-90B-compliance/20191113-040847 base:  
> https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git
> 01b59c763fe2de845b65900485b141fdd7bbf93e config: sh-allmodconfig (attached
> as .config)
> compiler: sh4-linux-gcc (GCC) 7.4.0
> reproduce:
>         wget
> https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O
> ~/bin/make.cross chmod +x ~/bin/make.cross
>         # save the attached .config to linux build tree
>         GCC_VERSION=7.4.0 make.cross ARCH=sh
> 
> If you fix the issue, kindly add following tag
> Reported-by: kbuild test robot <lkp@intel.com>
> 
> All warnings (new ones prefixed by >>):
> 
>    drivers/char/lrng/lrng_testing.c: In function 'lrng_raw_extract_user':
> >> drivers/char/lrng/lrng_testing.c:237:1: warning: the frame size of 1076
> >> bytes is larger than 1024 bytes [-Wframe-larger-than=]
>     }
>     ^
> 
> vim +237 drivers/char/lrng/lrng_testing.c
> 
>    196
>   
> 197	/**********************************************************************
> **** 198	 * Debugfs interface
>    199	
> **************************************************************************/
> 200	static int lrng_raw_extract_user(void __user *buf, size_t nbytes) 201	{
>    202		u8 tmp[LRNG_TESTING_RINGBUFFER_SIZE] 
__aligned(sizeof(u32));

This is the offending line.

I will need to kzalloc the code here.

Thank you.

>    203		int ret = 0, large_request = (nbytes > 256);
>    204
>    205		while (nbytes) {
>    206			int i;
>    207
>    208			if (large_request && need_resched()) {
>    209				if (signal_pending(current)) {
>    210					if (ret == 0)
>    211						ret = -ERESTARTSYS;
>    212					break;
>    213				}
>    214				schedule();
>    215			}
>    216
>    217			i = min_t(int, nbytes, sizeof(tmp));
>    218			i = lrng_raw_entropy_reader(tmp, i);
>    219			if (i <= 0) {
>    220				if (i < 0)
>    221					ret = i;
>    222				break;
>    223			}
>    224			if (copy_to_user(buf, tmp, i)) {
>    225				ret = -EFAULT;
>    226				break;
>    227			}
>    228
>    229			nbytes -= i;
>    230			buf = (u8 *)buf + i;
>    231			ret += i;
>    232		}
>    233
>    234		memzero_explicit(tmp, sizeof(tmp));
>    235
>    236		return ret;
> 
>  > 237	}
> 
>    238
> 
> ---
> 0-DAY kernel test infrastructure                 Open Source Technology
> Center https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org Intel
> Corporation


Ciao
Stephan



^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v24 01/12] Linux Random Number Generator
  2019-11-12 22:30   ` kbuild test robot
@ 2019-11-12 23:15     ` Stephan Müller
  0 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-12 23:15 UTC (permalink / raw)
  To: kbuild test robot
  Cc: kbuild-all, Arnd Bergmann, Greg Kroah-Hartman, linux-crypto,
	LKML, linux-api, Eric W. Biederman, Alexander E. Patrakov,
	Ahmed S. Darwish, Theodore Y. Ts'o, Willy Tarreau,
	Matthew Garrett, Vito Caputo, Andreas Dilger, Jan Kara,
	Ray Strode, William Jon McCann, zhangjs, Andy Lutomirski,
	Florian Weimer, Lennart Poettering, Nicolai Stange, Peter,
	Matthias, Marcelo Henrique Cerri, Roman Drahtmueller,
	Neil Horman

Am Dienstag, 12. November 2019, 23:30:29 CET schrieb kbuild test robot:

Hi kbuild,

> Hi "Stephan,
> 
> Thank you for the patch! Yet something to improve:
> 
> [auto build test ERROR on char-misc/char-misc-testing]
> [also build test ERROR on v5.4-rc7 next-20191112]
> [if your patch is applied to the wrong git tree, please drop us a note to
> help improve the system. BTW, we also suggest to use '--base' option to
> specify the base tree in git format-patch, please see
> https://stackoverflow.com/a/37406982]
> 
> url:   
> https://github.com/0day-ci/linux/commits/Stephan-M-ller/dev-random-a-new-ap
> proach-with-full-SP800-90B-compliance/20191113-040847 base:  
> https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git
> 01b59c763fe2de845b65900485b141fdd7bbf93e config:
> i386-randconfig-f003-201945 (attached as .config)
> compiler: gcc-7 (Debian 7.4.0-14) 7.4.0
> reproduce:
>         # save the attached .config to linux build tree
>         make ARCH=i386
> 
> If you fix the issue, kindly add following tag
> Reported-by: kbuild test robot <lkp@intel.com>
> 
> All errors (new ones prefixed by >>):
> 
>    In file included from <command-line>:0:0:
> 
>    include/linux/lrng.h: In function 'lrng_set_drng_cb':
> >> include/linux/lrng.h:80:61: error: 'EOPNOTSUPP' undeclared (first use in
> >> this function)

I need to include errno.h in lrng.h.

Thank you, it will be fixed in the next installment.

>     lrng_set_drng_cb(const struct lrng_crypto_cb *cb) { return -EOPNOTSUPP;
> } ^~~~~~~~~~ include/linux/lrng.h:80:61: note: each undeclared identifier
> is reported only once for each function it appears in
> 
> vim +/EOPNOTSUPP +80 include/linux/lrng.h
> 
>     74
>     75	/* Register cryptographic backend */
>     76	#ifdef CONFIG_LRNG_DRNG_SWITCH
>     77	int lrng_set_drng_cb(const struct lrng_crypto_cb *cb);
>     78	#else	/* CONFIG_LRNG_DRNG_SWITCH */
>     79	static inline int
> 
>   > 80	lrng_set_drng_cb(const struct lrng_crypto_cb *cb) { return
>   > -EOPNOTSUPP; }
>     81	#endif	/* CONFIG_LRNG_DRNG_SWITCH */
>     82
> 
> ---
> 0-DAY kernel test infrastructure                 Open Source Technology
> Center https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org Intel
> Corporation


Ciao
Stephan



^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v24 00/12] /dev/random - a new approach with full SP800-90B compliance
  2019-11-12 23:03   ` Stephan Müller
@ 2019-11-12 23:26     ` Stephan Müller
  0 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-12 23:26 UTC (permalink / raw)
  To: Stephan Müller
  Cc: Andy Lutomirski, Arnd Bergmann, Greg Kroah-Hartman,
	Linux Crypto Mailing List, LKML, Linux API, Eric W. Biederman,
	Alexander E. Patrakov, Ahmed S. Darwish, Theodore Y. Ts'o,
	Willy Tarreau, Matthew Garrett, Vito Caputo, Andreas Dilger,
	Jan Kara, Ray Strode, William Jon McCann, zhangjs,
	Florian Weimer, Lennart Poettering, Nicolai Stange, Peter,
	Matthias, Marcelo Henrique Cerri, Roman Drahtmueller,
	Neil Horman

Am Mittwoch, 13. November 2019, 00:03:47 CET schrieb Stephan Müller:

Hi Stephan,

> Am Dienstag, 12. November 2019, 16:33:59 CET schrieb Andy Lutomirski:
> 
> Hi Andy,
> 
> > On Mon, Nov 11, 2019 at 11:13 AM Stephan Müller <smueller@chronox.de> 
wrote:
> > > The following patch set provides a different approach to /dev/random
> > > which
> > > is called Linux Random Number Generator (LRNG) to collect entropy within
> > > the Linux kernel. The main improvements compared to the existing
> > > /dev/random is to provide sufficient entropy during boot time as well as
> > > in virtual environments and when using SSDs. A secondary design goal is
> > > to limit the impact of the entropy collection on massive parallel
> > > systems
> > > and also allow the use accelerated cryptographic primitives. Also, all
> > > steps of the entropic data processing are testable.
> > 
> > This is very nice!
> > 
> > > The LRNG patch set allows a user to select use of the existing
> > > /dev/random
> > > or the LRNG during compile time. As the LRNG provides API and ABI
> > > compatible interfaces to the existing /dev/random implementation, the
> > > user can freely chose the RNG implementation without affecting kernel or
> > > user space operations.
> > > 
> > > This patch set provides early boot-time entropy which implies that no
> > > additional flags to the getrandom(2) system call discussed recently on
> > > the LKML is considered to be necessary.
> > 
> > I'm uneasy about this.  I fully believe that, *on x86*, this works.
> > But on embedded systems with in-order CPUs, a single clock, and very
> > lightweight boot processes, most or all of boot might be too
> > deterministic for this to work.
> 
> I agree that in such cases, my LRNG getrandom(2) would also block until the
> LRNG thinks it collected 256 bits of entropy. However, I am under the
> impression that the LRNG collects that entropy faster that the existing
> /dev/ random implementation, even in this case.
> 
> Nicolai is copied on this thread. He promised to have the LRNG tested on
> such a minimalistic system that you describe. I hope he could contribute
> some numbers from that test helping us to understand how much of a problem
> we face.
> > I have a somewhat competing patch set here:
> > 
> > https://git.kernel.org/pub/scm/linux/kernel/git/luto/linux.git/log/?h=rand
> > om /kill-it
> > 
> > (Ignore the "horrible test hack" and the debugfs part.)
> > 
> > The basic summary is that I change /dev/random so that it becomes
> > functionally identical to getrandom(..., 0) -- in other words, it
> > blocks until the CRNG is initialized but is then identical to
> > /dev/urandom.
> 
> This would be equal to the LRNG code without compiling the TRNG.
> 
> > And I add getrandom(...., GRND_INSECURE) that is
> > functionally identical to the existing /dev/urandom: it always returns
> > *something* immediately, but it may or may not actually be
> > cryptographically random or even random at all depending on system
> > details.
> 
> Ok, if it is suggested that getrandom(2) should also have a mode to behave
> exactly like /dev/urandom by not waiting until it is fully seeded, I am
> happy to add that.
> 
> > In other words, my series simplifies the ABI that we support.  Right
> > now, we have three ways to ask for random numbers with different
> > semantics and we need to have to RNGs in the kernel at all time.  With
> > my changes, we have only two ways to ask for random numbers, and the
> > /dev/random pool is entirely gone.
> 
> Again, I do not want to stand in the way of changing the ABI if this is the
> agreed way. All I want to say is that the LRNG seemingly is initialized much
> faster than the existing /dev/random. If this is not fast enough for some
> embedded environments, I would not want to stand in the way to make their
> life easier.
> 
> > Would you be amenable to merging this into your series (i.e. either
> > merging the code or just the ideas)?
> 
> Absolutely. I would be happy to do that.
> 
> Allow me to pull your code (I am currently behind a slow line) and review it
> to see how best to integrate it.
> 
> > This would let you get rid of
> > things like the compile-time selection of the blocking TRNG, since the
> > blocking TRNG would be entirely gone.
> 
> Hm, I am not so sure we should do that.
> 
> Allow me to explain: I am also collaborating on the European side with the
> German BSI. They love /dev/random as it is a "NTG.1" RNG based on their AIS
> 31 standard.
> 
> In order to seed a deterministic RNG (like OpenSSL, GnuTLS, etc. which are
> all defined to be "DRG.3" or "DRG.2"), BSI mandates that the seed source is
> an NTG.1.
> 
> By getting rid of the TRNG entirely and having /dev/random entirely behaving
> like /dev/urandom or getrandom(2) without the GRND_RANDOM flag, the kernel
> would "only" provide a "DRG.3" type RNG. This type of RNG would be
> disallowed to seed another "DRG.3" or "DRG.2".
> 
> In plain English that means that for BSI's requirements, if the TRNG is gone
> there would be no native seed source on Linux any more that can satisfy the
> requirement. This is the ultimate reason why I made the TRNG compile-time
> selectable: to support embedded systems but also support use cases like the
> BSI case.
> 
> Please consider that I maintain a study over the last years for BSI trying
> to ensure that the NTG.1 property is always met [1] [2]. The sole purpose
> of that study is around this NTG.1.
> 
> > Or do you think that a kernel-provided blocking TRNG is a genuinely
> > useful thing to keep around?
> 
> Yes, as I hope I explained it appropriately above, there are standardization
> requirements that need the TRNG.
> 
> PS: When I was forwarding Linus' email on eliminating the blocking_pool to
> BSI, I saw unhappy faces. :-)
> 
> I would like to help both sides here.
> 
> [1]
> https://www.bsi.bund.de/SharedDocs/Downloads/EN/BSI/Publications/Studies/
> LinuxRNG/NTG1_Kerneltabelle_EN.pdf?__blob=publicationFile&v=3
> 
> [2]
> https://www.bsi.bund.de/SharedDocs/Downloads/EN/BSI/Publications/Studies/
> LinuxRNG/NTG1_Kerneltabelle_EN.pdf?__blob=publicationFile&v=3

Sorry, the copy did not work:

[2] https://bsi.bund.de/SharedDocs/Downloads/EN/BSI/Publications/Studies/
LinuxRNG/LinuxRNG_EN.pdf?__blob=publicationFile&v=16
> 
> Ciao
> Stephan


Ciao
Stephan



^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v24 01/12] Linux Random Number Generator
  2019-11-11 18:18 ` [PATCH v24 01/12] Linux Random Number Generator Stephan Müller
  2019-11-11 23:54   ` Thomas Gleixner
  2019-11-12 22:30   ` kbuild test robot
@ 2019-11-13  0:14   ` kbuild test robot
  2019-11-13  0:25     ` Stephan Müller
  2019-11-24  4:51   ` Sandy Harris
  3 siblings, 1 reply; 162+ messages in thread
From: kbuild test robot @ 2019-11-13  0:14 UTC (permalink / raw)
  To: Stephan Müller
  Cc: kbuild-all, Arnd Bergmann, Greg Kroah-Hartman, linux-crypto,
	LKML, linux-api, Eric W. Biederman, Alexander E. Patrakov,
	Ahmed S. Darwish, Theodore Y. Ts'o, Willy Tarreau,
	Matthew Garrett, Vito Caputo, Andreas Dilger, Jan Kara,
	Ray Strode, William Jon McCann, zhangjs, Andy Lutomirski,
	Florian Weimer, Lennart Poettering, Nicolai Stange, Peter,
	Matthias, Marcelo Henrique Cerri, Roman Drahtmueller,
	Neil Horman

[-- Attachment #1: Type: text/plain, Size: 2677 bytes --]

Hi "Stephan,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on char-misc/char-misc-testing]
[also build test ERROR on v5.4-rc7 next-20191112]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]

url:    https://github.com/0day-ci/linux/commits/Stephan-M-ller/dev-random-a-new-approach-with-full-SP800-90B-compliance/20191113-040847
base:   https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git 01b59c763fe2de845b65900485b141fdd7bbf93e
config: mips-allmodconfig (attached as .config)
compiler: mips-linux-gcc (GCC) 7.4.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        GCC_VERSION=7.4.0 make.cross ARCH=mips 

If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   drivers/char/lrng/lrng_sw_noise.c: In function 'add_interrupt_randomness':
>> drivers/char/lrng/lrng_sw_noise.c:145:23: error: invalid application of 'sizeof' to incomplete type 'struct pt_regs'
       size_t n = (sizeof(struct pt_regs) / sizeof(u32));
                          ^~~~~~
>> drivers/char/lrng/lrng_sw_noise.c:147:9: error: implicit declaration of function 'instruction_pointer'; did you mean 'instruction_hazard'? [-Werror=implicit-function-declaration]
       ip = instruction_pointer(regs);
            ^~~~~~~~~~~~~~~~~~~
            instruction_hazard
   cc1: some warnings being treated as errors

vim +145 drivers/char/lrng/lrng_sw_noise.c

   125	
   126	/**
   127	 * Hot code path - Callback for interrupt handler
   128	 */
   129	void add_interrupt_randomness(int irq, int irq_flags)
   130	{
   131		lrng_time_process();
   132	
   133		if (!lrng_pool_highres_timer()) {
   134			struct pt_regs *regs = get_irq_regs();
   135			static atomic_t reg_idx = ATOMIC_INIT(0);
   136			u64 ip;
   137	
   138			lrng_pool_lfsr_u32(jiffies);
   139			lrng_pool_lfsr_u32(irq);
   140			lrng_pool_lfsr_u32(irq_flags);
   141	
   142			if (regs) {
   143				u32 *ptr = (u32 *)regs;
   144				int reg_ptr = atomic_add_return_relaxed(1, &reg_idx);
 > 145				size_t n = (sizeof(struct pt_regs) / sizeof(u32));
   146	
 > 147				ip = instruction_pointer(regs);

---
0-DAY kernel test infrastructure                 Open Source Technology Center
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 62104 bytes --]

^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v24 01/12] Linux Random Number Generator
  2019-11-13  0:14   ` kbuild test robot
@ 2019-11-13  0:25     ` Stephan Müller
  0 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-13  0:25 UTC (permalink / raw)
  To: kbuild test robot
  Cc: kbuild-all, Arnd Bergmann, Greg Kroah-Hartman, linux-crypto,
	LKML, linux-api, Eric W. Biederman, Alexander E. Patrakov,
	Ahmed S. Darwish, Theodore Y. Ts'o, Willy Tarreau,
	Matthew Garrett, Vito Caputo, Andreas Dilger, Jan Kara,
	Ray Strode, William Jon McCann, zhangjs, Andy Lutomirski,
	Florian Weimer, Lennart Poettering, Nicolai Stange, Peter,
	Matthias, Marcelo Henrique Cerri, Roman Drahtmueller,
	Neil Horman

Am Mittwoch, 13. November 2019, 01:14:05 CET schrieb kbuild test robot:

Hi kbuild,

> Hi "Stephan,
> 
> Thank you for the patch! Yet something to improve:
> 
> [auto build test ERROR on char-misc/char-misc-testing]
> [also build test ERROR on v5.4-rc7 next-20191112]
> [if your patch is applied to the wrong git tree, please drop us a note to
> help improve the system. BTW, we also suggest to use '--base' option to
> specify the base tree in git format-patch, please see
> https://stackoverflow.com/a/37406982]
> 
> url:   
> https://github.com/0day-ci/linux/commits/Stephan-M-ller/dev-random-a-new-ap
> proach-with-full-SP800-90B-compliance/20191113-040847 base:  
> https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git
> 01b59c763fe2de845b65900485b141fdd7bbf93e config: mips-allmodconfig
> (attached as .config)
> compiler: mips-linux-gcc (GCC) 7.4.0
> reproduce:
>         wget
> https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O
> ~/bin/make.cross chmod +x ~/bin/make.cross
>         # save the attached .config to linux build tree
>         GCC_VERSION=7.4.0 make.cross ARCH=mips
> 
> If you fix the issue, kindly add following tag
> Reported-by: kbuild test robot <lkp@intel.com>
> 
> All errors (new ones prefixed by >>):
> 
>    drivers/char/lrng/lrng_sw_noise.c: In function 
'add_interrupt_randomness':
> >> drivers/char/lrng/lrng_sw_noise.c:145:23: error: invalid application of
> >> 'sizeof' to incomplete type 'struct pt_regs'
>        size_t n = (sizeof(struct pt_regs) / sizeof(u32));
>                           ^~~~~~
> 
> >> drivers/char/lrng/lrng_sw_noise.c:147:9: error: implicit declaration of
> >> function 'instruction_pointer'; did you mean 'instruction_hazard'?
> >> [-Werror=implicit-function-declaration]
>        ip = instruction_pointer(regs);
>             ^~~~~~~~~~~~~~~~~~~
>             instruction_hazard
>    cc1: some warnings being treated as errors
> 
> vim +145 drivers/char/lrng/lrng_sw_noise.c

Thank you for the report.

Both issues are fixed by including <asm/ptrace.h>.

This will be fixed with the next installment of the patch.
> 
>    125
>    126	/**
>    127	 * Hot code path - Callback for interrupt handler
>    128	 */
>    129	void add_interrupt_randomness(int irq, int irq_flags)
>    130	{
>    131		lrng_time_process();
>    132
>    133		if (!lrng_pool_highres_timer()) {
>    134			struct pt_regs *regs = get_irq_regs();
>    135			static atomic_t reg_idx = ATOMIC_INIT(0);
>    136			u64 ip;
>    137
>    138			lrng_pool_lfsr_u32(jiffies);
>    139			lrng_pool_lfsr_u32(irq);
>    140			lrng_pool_lfsr_u32(irq_flags);
>    141
>    142			if (regs) {
>    143				u32 *ptr = (u32 *)regs;
>    144				int reg_ptr = atomic_add_return_relaxed(1, 
&reg_idx);
> 
>  > 145				size_t n = (sizeof(struct pt_regs) / 
sizeof(u32));
> 
>    146
> 
>  > 147				ip = instruction_pointer(regs);
> 
> ---
> 0-DAY kernel test infrastructure                 Open Source Technology
> Center https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org Intel
> Corporation


Ciao
Stephan



^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v24 11/12] LRNG - add SP800-90B compliant health tests
  2019-11-12 19:58   ` Alexander E. Patrakov
  2019-11-12 23:11     ` Stephan Müller
@ 2019-11-13  0:36     ` Stephan Müller
  2019-11-13  6:02       ` Alexander E. Patrakov
  1 sibling, 1 reply; 162+ messages in thread
From: Stephan Müller @ 2019-11-13  0:36 UTC (permalink / raw)
  To: Alexander E. Patrakov
  Cc: Arnd Bergmann, Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Ahmed S. Darwish, Theodore Y. Ts'o,
	Willy Tarreau, Matthew Garrett, Vito Caputo, Andreas Dilger,
	Jan Kara, Ray Strode, William Jon McCann, zhangjs,
	Andy Lutomirski, Florian Weimer, Lennart Poettering,
	Nicolai Stange, Peter, Matthias, Marcelo Henrique Cerri,
	Roman Drahtmueller, Neil Horman

Am Dienstag, 12. November 2019, 20:58:32 CET schrieb Alexander E. Patrakov:

Hi Alexander,
 
> > +config LRNG_HEALTH_TESTS
> > +	bool "Enable noise source online health tests"
> > +	help
> > +	  The online health tests validate the noise source at
> > +	  runtime for fatal errors. These tests include SP800-90B
> > +	  compliant tests which are invoked if the system is booted
> > +	  with fips=1. In case of fatal errors during active
> > +	  SP800-90B tests, the issue is logged and the noise
> > +	  data is discarded. These tests are required for full
> > +	  compliance with SP800-90B.
> 
> How have you tested that these tests work at runtime? Maybe add some
> code under a new CONFIG item that depends on CONFIG_BROKEN that
> deliberately botches the RNG and triggers failures?


I am unable to find sensible information about CONFIG_BROKEN in the recent 
kernel tree. 

Do you happen to have a pointer on how that option is to be used?

Thanks a lot

Ciao
Stephan



^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v24 00/12] /dev/random - a new approach with full SP800-90B compliance
  2019-11-12 15:33 ` Andy Lutomirski
  2019-11-12 23:03   ` Stephan Müller
@ 2019-11-13  4:24   ` Stephan Müller
  2019-11-13  4:48     ` Andy Lutomirski
  1 sibling, 1 reply; 162+ messages in thread
From: Stephan Müller @ 2019-11-13  4:24 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Arnd Bergmann, Greg Kroah-Hartman, Linux Crypto Mailing List,
	LKML, Linux API, Eric W. Biederman, Alexander E. Patrakov,
	Ahmed S. Darwish, Theodore Y. Ts'o, Willy Tarreau,
	Matthew Garrett, Vito Caputo, Andreas Dilger, Jan Kara,
	Ray Strode, William Jon McCann, zhangjs, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

Am Dienstag, 12. November 2019, 16:33:59 CET schrieb Andy Lutomirski:

Hi Andy,

> On Mon, Nov 11, 2019 at 11:13 AM Stephan Müller <smueller@chronox.de> wrote:
> > The following patch set provides a different approach to /dev/random which
> > is called Linux Random Number Generator (LRNG) to collect entropy within
> > the Linux kernel. The main improvements compared to the existing
> > /dev/random is to provide sufficient entropy during boot time as well as
> > in virtual environments and when using SSDs. A secondary design goal is
> > to limit the impact of the entropy collection on massive parallel systems
> > and also allow the use accelerated cryptographic primitives. Also, all
> > steps of the entropic data processing are testable.
> 
> This is very nice!
> 
> > The LRNG patch set allows a user to select use of the existing /dev/random
> > or the LRNG during compile time. As the LRNG provides API and ABI
> > compatible interfaces to the existing /dev/random implementation, the
> > user can freely chose the RNG implementation without affecting kernel or
> > user space operations.
> > 
> > This patch set provides early boot-time entropy which implies that no
> > additional flags to the getrandom(2) system call discussed recently on
> > the LKML is considered to be necessary.
> 
> I'm uneasy about this.  I fully believe that, *on x86*, this works.
> But on embedded systems with in-order CPUs, a single clock, and very
> lightweight boot processes, most or all of boot might be too
> deterministic for this to work.
> 
> I have a somewhat competing patch set here:
> 
> https://git.kernel.org/pub/scm/linux/kernel/git/luto/linux.git/log/?h=random
> /kill-it
> 
> (Ignore the "horrible test hack" and the debugfs part.)
> 
> The basic summary is that I change /dev/random so that it becomes
> functionally identical to getrandom(..., 0) -- in other words, it
> blocks until the CRNG is initialized but is then identical to
> /dev/urandom.  And I add getrandom(...., GRND_INSECURE) that is
> functionally identical to the existing /dev/urandom: it always returns
> *something* immediately, but it may or may not actually be
> cryptographically random or even random at all depending on system
> details.
> 
> In other words, my series simplifies the ABI that we support.  Right
> now, we have three ways to ask for random numbers with different
> semantics and we need to have to RNGs in the kernel at all time.  With
> my changes, we have only two ways to ask for random numbers, and the
> /dev/random pool is entirely gone.
> 
> Would you be amenable to merging this into your series (i.e. either
> merging the code or just the ideas)?  This would let you get rid of
> things like the compile-time selection of the blocking TRNG, since the
> blocking TRNG would be entirely gone.

I pulled your code and found the following based on my explanation that I 
would suggest to keep the TRNG at least as an option.

- 7d54ef8512b06baf396f12584f7f48a9558ecd0f does not seem applicable: I also do 
have an equivalent "lrng_init_wait" wait queue. This wait queue is used to let 
in-kernel users wait until the LRNG obtained 128 bits of entropy. In addition, 
this wait queue is used to let user space is invoked after the LRNG has 
received 256 bits of entropy (which implies that the kernel waiters are 
invoked earlier). In kernel waiters are all that call wait_for_random_bytes 
and its derivatives. User space callers have to call getrandom(..., 0); to be 
registered in this wait queue. So, I think the wakeup calls I have in the LRNG 
for lrng_init_wait should remain.

- 6a26a3146e5fb90878dca9fde8caa1ca4233156a: My handler for /dev/urandom and 
getrandom(..., 0) are using one callback which issues a warning in both use 
cases (see lrng_sdrng_read). So I think this patch may not be applicable as 
the LRNG code implements warning about being unseeded.

- 3e8e159da49b44ae0bb08e68fa2be760722fa033: I am happy to take that code which 
would almost directly apply. The last hunk however would be:

if (!(flags & GRND_INSECURE) && unlikely(!lrng_state_operational())) {

==> Shall I apply it to my code base? If yes, how shall the changes to 
random.h be handled?


- 920e97e7fc508e6f0da9c7dec94c8073fd63ab4d: I would pass on this patch due to 
the following: it unconditionally starts removing the access to the TRNG (the 
LRNG's logical equivalent to the blocking_pool). As patch 10/12 of the LRNG 
patch series provides the TRNG that is a compile time option, your patch would 
logically and functionally be equivalent when deselecting 
CONFIG_LRNG_TRNG_SUPPORT in the LRNG without any further changes to the LRNG 
code.

- 693b9ffdf0fdc93456b5ad293ac05edf240a531b: This patch is applicable to the 
LRNG. In case CONFIG_LRNG_TRNG_SUPPORT is not set, the TRNG is not present. 
Yet, the /dev/random and getrandom(GRND_RANDOM) would behave blocked until 
fully initialized. I have now added the general blocking until the LRNG is 
fully initialized to the common /dev/random and getrandom(GRND_RANDOM) 
interface function of lrng_trng_read_common. With that, the LRNG would be 
fully equivalent to this patch if CONFIG_LRNG_TRNG_SUPPORT is not set.

- 66f660842ec6d34134b9c3c1c9c65972834797f6: This patch is implicit with 
CONFIG_LRNG_TRNG_SUPPORT being not set.

- d8f59b5c25af22fb9d85b7fa96de601ea03f2eac: This patch is not applicable to 
the LRNG as the deactivation of CONFIG_LRNG_TRNG_SUPPORT implies that there 
should be no unused code left in the LRNG.

- 4046ac638761821aef67af10537ebcbc80715785: In theory that patch is applicable 
to the LRNG as well. The LRNG has the lrng_read_wait queue. If 
CONFIG_LRNG_TRNG_SUPPORT is not set, there will never be the code triggered to 
add a caller to this wait queue. To avoid cluttering the LRNG code with 
ifdefs, may I suggest to leave these several lines even though it is dead 
code?



Bottom line: the only patch that I seems to be relevant and that I would be 
happy to apply is the one adding GRND_INSECURE. All other patches are 
implicitly covered by deselecting CONFIG_LRNG_TRNG_SUPPORT.

By making the TRNG compile-time selectable, I was hoping to serve all users: I 
wanted to cover the conclusions of the discussion to remove the blocking_pool. 
On the other hand, however, I want to support requirements that need the 
blocking behavior.

The current LRNG patch set, however, defaults to Y for 
CONFIG_LRNG_TRNG_SUPPORT. I would see no issue if it defaults to N.


Thank you very much.

Ciao
Stephan



^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v24 00/12] /dev/random - a new approach with full SP800-90B compliance
  2019-11-13  4:24   ` Stephan Müller
@ 2019-11-13  4:48     ` Andy Lutomirski
  2019-11-13 12:16       ` Stephan Müller
  0 siblings, 1 reply; 162+ messages in thread
From: Andy Lutomirski @ 2019-11-13  4:48 UTC (permalink / raw)
  To: Stephan Müller
  Cc: Andy Lutomirski, Arnd Bergmann, Greg Kroah-Hartman,
	Linux Crypto Mailing List, LKML, Linux API, Eric W. Biederman,
	Alexander E. Patrakov, Ahmed S. Darwish, Theodore Y. Ts'o,
	Willy Tarreau, Matthew Garrett, Vito Caputo, Andreas Dilger,
	Jan Kara, Ray Strode, William Jon McCann, zhangjs,
	Florian Weimer, Lennart Poettering, Nicolai Stange, Peter,
	Matthias, Marcelo Henrique Cerri, Roman Drahtmueller,
	Neil Horman

On Tue, Nov 12, 2019 at 8:25 PM Stephan Müller <smueller@chronox.de> wrote:
>
> Am Dienstag, 12. November 2019, 16:33:59 CET schrieb Andy Lutomirski:
>
> Hi Andy,
>
> > On Mon, Nov 11, 2019 at 11:13 AM Stephan Müller <smueller@chronox.de> wrote:
> > > The following patch set provides a different approach to /dev/random which
> > > is called Linux Random Number Generator (LRNG) to collect entropy within
> > > the Linux kernel. The main improvements compared to the existing
> > > /dev/random is to provide sufficient entropy during boot time as well as
> > > in virtual environments and when using SSDs. A secondary design goal is
> > > to limit the impact of the entropy collection on massive parallel systems
> > > and also allow the use accelerated cryptographic primitives. Also, all
> > > steps of the entropic data processing are testable.
> >
> > This is very nice!
> >
> > > The LRNG patch set allows a user to select use of the existing /dev/random
> > > or the LRNG during compile time. As the LRNG provides API and ABI
> > > compatible interfaces to the existing /dev/random implementation, the
> > > user can freely chose the RNG implementation without affecting kernel or
> > > user space operations.
> > >
> > > This patch set provides early boot-time entropy which implies that no
> > > additional flags to the getrandom(2) system call discussed recently on
> > > the LKML is considered to be necessary.
> >
> > I'm uneasy about this.  I fully believe that, *on x86*, this works.
> > But on embedded systems with in-order CPUs, a single clock, and very
> > lightweight boot processes, most or all of boot might be too
> > deterministic for this to work.
> >
> > I have a somewhat competing patch set here:
> >
> > https://git.kernel.org/pub/scm/linux/kernel/git/luto/linux.git/log/?h=random
> > /kill-it
> >
> > (Ignore the "horrible test hack" and the debugfs part.)
> >
> > The basic summary is that I change /dev/random so that it becomes
> > functionally identical to getrandom(..., 0) -- in other words, it
> > blocks until the CRNG is initialized but is then identical to
> > /dev/urandom.  And I add getrandom(...., GRND_INSECURE) that is
> > functionally identical to the existing /dev/urandom: it always returns
> > *something* immediately, but it may or may not actually be
> > cryptographically random or even random at all depending on system
> > details.
> >
> > In other words, my series simplifies the ABI that we support.  Right
> > now, we have three ways to ask for random numbers with different
> > semantics and we need to have to RNGs in the kernel at all time.  With
> > my changes, we have only two ways to ask for random numbers, and the
> > /dev/random pool is entirely gone.
> >
> > Would you be amenable to merging this into your series (i.e. either
> > merging the code or just the ideas)?  This would let you get rid of
> > things like the compile-time selection of the blocking TRNG, since the
> > blocking TRNG would be entirely gone.
>
> I pulled your code and found the following based on my explanation that I
> would suggest to keep the TRNG at least as an option.
>
> - 7d54ef8512b06baf396f12584f7f48a9558ecd0f does not seem applicable:

Not surprising.  It's just a cleanup to the existing code, and I doubt
you inherited the oddity I'm fixing.

> - 6a26a3146e5fb90878dca9fde8caa1ca4233156a: My handler for /dev/urandom and
> getrandom(..., 0) are using one callback which issues a warning in both use
> cases (see lrng_sdrng_read). So I think this patch may not be applicable as
> the LRNG code implements warning about being unseeded.

Probably true.

What is the actual semantics of /dev/urandom with your series applied?
 Is there any situation in which it will block?

>
> - 3e8e159da49b44ae0bb08e68fa2be760722fa033: I am happy to take that code which
> would almost directly apply. The last hunk however would be:
>
> if (!(flags & GRND_INSECURE) && unlikely(!lrng_state_operational())) {
>
> ==> Shall I apply it to my code base? If yes, how shall the changes to
> random.h be handled?
>

This might be a question for Ted.  Once the merge window opens, I'll
resubmit it.

>
> - 920e97e7fc508e6f0da9c7dec94c8073fd63ab4d: I would pass on this patch due to
> the following: it unconditionally starts removing the access to the TRNG (the
> LRNG's logical equivalent to the blocking_pool). As patch 10/12 of the LRNG
> patch series provides the TRNG that is a compile time option, your patch would
> logically and functionally be equivalent when deselecting
> CONFIG_LRNG_TRNG_SUPPORT in the LRNG without any further changes to the LRNG
> code.

Given your previous email about the TRNG, I'm wondering what the API
for the TRNG should be.  I am willing to grant that there are users
who need a TRNG for various reasons, and that not all of them can use
hwrng.  (And the current hwrng API is pretty bad.)  But I'm not
convinced that /dev/random or getrandom(..., GRND_RANDOM) is a
reasonable way to access it.  A blocking_pool-style TRNG is a very
limited resource, and I think it could make sense to require some sort
of actual permission to use it.  GRND_RANDOM has no access control at
all, and everyone expects /dev/random to be world-readable.  The most
widespread user of /dev/random that I know of is gnupg, and gnupg
really should not be using it.

Would it make sense to have a /dev/true_random that is 0400 by default
for users who actually need it?  Then /dev/random and GRND_RANDOM
could work as they do with my patch, and maybe it does the right thing
for everyone.

>
> - 693b9ffdf0fdc93456b5ad293ac05edf240a531b: This patch is applicable to the
> LRNG. In case CONFIG_LRNG_TRNG_SUPPORT is not set, the TRNG is not present.
> Yet, the /dev/random and getrandom(GRND_RANDOM) would behave blocked until
> fully initialized. I have now added the general blocking until the LRNG is
> fully initialized to the common /dev/random and getrandom(GRND_RANDOM)
> interface function of lrng_trng_read_common. With that, the LRNG would be
> fully equivalent to this patch if CONFIG_LRNG_TRNG_SUPPORT is not set.

Sounds reasonable.

> By making the TRNG compile-time selectable, I was hoping to serve all users: I
> wanted to cover the conclusions of the discussion to remove the blocking_pool.
> On the other hand, however, I want to support requirements that need the
> blocking behavior.

I find it odd that /dev/random would be either a TRNG or not a TRNG
depending on kernel configuration.  For the small fraction of users
that actually want a TRNG, wouldn't it be better to have an interface
that fails outright if the TRNG is not enabled?

--Andy

^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v24 11/12] LRNG - add SP800-90B compliant health tests
  2019-11-13  0:36     ` Stephan Müller
@ 2019-11-13  6:02       ` Alexander E. Patrakov
  2019-11-14  1:46         ` Stephan Müller
  0 siblings, 1 reply; 162+ messages in thread
From: Alexander E. Patrakov @ 2019-11-13  6:02 UTC (permalink / raw)
  To: Stephan Müller
  Cc: Arnd Bergmann, Greg Kroah-Hartman, linux-crypto, LKML, Linux API,
	Eric W. Biederman, Ahmed S. Darwish, Theodore Y. Ts'o,
	Willy Tarreau, Matthew Garrett, Vito Caputo, Andreas Dilger,
	Jan Kara, Ray Strode, William Jon McCann, zhangjs,
	Andy Lutomirski, Florian Weimer, Lennart Poettering,
	Nicolai Stange, Peter, Matthias, Marcelo Henrique Cerri,
	Roman Drahtmueller, Neil Horman

ср, 13 нояб. 2019 г. в 05:38, Stephan Müller <smueller@chronox.de>:
>
> Am Dienstag, 12. November 2019, 20:58:32 CET schrieb Alexander E. Patrakov:
>
> Hi Alexander,
>
> > > +config LRNG_HEALTH_TESTS
> > > +   bool "Enable noise source online health tests"
> > > +   help
> > > +     The online health tests validate the noise source at
> > > +     runtime for fatal errors. These tests include SP800-90B
> > > +     compliant tests which are invoked if the system is booted
> > > +     with fips=1. In case of fatal errors during active
> > > +     SP800-90B tests, the issue is logged and the noise
> > > +     data is discarded. These tests are required for full
> > > +     compliance with SP800-90B.
> >
> > How have you tested that these tests work at runtime? Maybe add some
> > code under a new CONFIG item that depends on CONFIG_BROKEN that
> > deliberately botches the RNG and triggers failures?
>
>
> I am unable to find sensible information about CONFIG_BROKEN in the recent
> kernel tree.
>
> Do you happen to have a pointer on how that option is to be used?

This option is not used on its own. You create a new option,
CONFIG_TEST_LRNG_FAILURE_MODE or something like that, and put your
code under the ifdef guarded by that option. And then, to prevent
ordinary users and allyesconfig from selecting it, in Kconfig you say:
"depends on BROKEN". This way, the option becomes unselectable in
menuconfig but still works as intended when added manually to .config
(obviously, with the BROKEN dependency removed locally).

Definition: https://github.com/torvalds/linux/blob/9c7db5004280767566e91a33445bf93aa479ef02/init/Kconfig#L68
Example usage: https://github.com/torvalds/linux/blob/c87237110f2553b4200a8b3401a01198edfcf0d9/drivers/gpu/drm/i915/Kconfig.debug#L166

--
Alexander E. Patrakov

^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v24 00/12] /dev/random - a new approach with full SP800-90B compliance
  2019-11-13  4:48     ` Andy Lutomirski
@ 2019-11-13 12:16       ` Stephan Müller
  0 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-13 12:16 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Arnd Bergmann, Greg Kroah-Hartman, Linux Crypto Mailing List,
	LKML, Linux API, Eric W. Biederman, Alexander E. Patrakov,
	Ahmed S. Darwish, Theodore Y. Ts'o, Willy Tarreau,
	Matthew Garrett, Vito Caputo, Andreas Dilger, Jan Kara,
	Ray Strode, William Jon McCann, zhangjs, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

Am Mittwoch, 13. November 2019, 05:48:30 CET schrieb Andy Lutomirski:

Hi Andy,

> 
> > - 6a26a3146e5fb90878dca9fde8caa1ca4233156a: My handler for /dev/urandom
> > and
> > getrandom(..., 0) are using one callback which issues a warning in both
> > use
> > cases (see lrng_sdrng_read). So I think this patch may not be applicable
> > as
> > the LRNG code implements warning about being unseeded.
> 
> Probably true.
> 
> What is the actual semantics of /dev/urandom with your series applied?
>  Is there any situation in which it will block?

The LRNG tries to provide a 100% identical user interface to the existing /
dev/random:

- /dev/urandom never blocks

- getrandom(..., 0) blocks until the LRNG has received 256 bits of entropy 
(i.e. the LRNG is fully seeded)

Yet, both may issue a warning if CONFIG_WARN_ALL_UNSEEDED_RANDOM is set.
> 
> > - 3e8e159da49b44ae0bb08e68fa2be760722fa033: I am happy to take that code
> > which would almost directly apply. The last hunk however would be:
> > 
> > if (!(flags & GRND_INSECURE) && unlikely(!lrng_state_operational())) {
> > 
> > ==> Shall I apply it to my code base? If yes, how shall the changes to
> > random.h be handled?
> 
> This might be a question for Ted.  Once the merge window opens, I'll
> resubmit it.

Ok, I will keep it out of the LRNG for now, but once your patch is merged, I 
would integrate it.
> 
> > - 920e97e7fc508e6f0da9c7dec94c8073fd63ab4d: I would pass on this patch due
> > to the following: it unconditionally starts removing the access to the
> > TRNG (the LRNG's logical equivalent to the blocking_pool). As patch 10/12
> > of the LRNG patch series provides the TRNG that is a compile time option,
> > your patch would logically and functionally be equivalent when
> > deselecting
> > CONFIG_LRNG_TRNG_SUPPORT in the LRNG without any further changes to the
> > LRNG code.
> 
> Given your previous email about the TRNG, I'm wondering what the API
> for the TRNG should be.  I am willing to grant that there are users
> who need a TRNG for various reasons, and that not all of them can use
> hwrng.  (And the current hwrng API is pretty bad.)  But I'm not
> convinced that /dev/random or getrandom(..., GRND_RANDOM) is a
> reasonable way to access it.  A blocking_pool-style TRNG is a very
> limited resource, and I think it could make sense to require some sort
> of actual permission to use it.  GRND_RANDOM has no access control at
> all, and everyone expects /dev/random to be world-readable.  The most
> widespread user of /dev/random that I know of is gnupg, and gnupg
> really should not be using it.
> 
> Would it make sense to have a /dev/true_random that is 0400 by default
> for users who actually need it?  Then /dev/random and GRND_RANDOM
> could work as they do with my patch, and maybe it does the right thing
> for everyone.

That is surely a reasonable way to do it. But I am not sure 0400 should be 
applied, but rather 0440. This should allow introducing a group in user space 
that processes who need the TRNG are not required to have root privilege, but 
rather need to be a member of some otherwise unprivileged group.
> 
> > - 693b9ffdf0fdc93456b5ad293ac05edf240a531b: This patch is applicable to
> > the
> > LRNG. In case CONFIG_LRNG_TRNG_SUPPORT is not set, the TRNG is not
> > present.
> > Yet, the /dev/random and getrandom(GRND_RANDOM) would behave blocked until
> > fully initialized. I have now added the general blocking until the LRNG is
> > fully initialized to the common /dev/random and getrandom(GRND_RANDOM)
> > interface function of lrng_trng_read_common. With that, the LRNG would be
> > fully equivalent to this patch if CONFIG_LRNG_TRNG_SUPPORT is not set.
> 
> Sounds reasonable.
> 
> > By making the TRNG compile-time selectable, I was hoping to serve all
> > users: I wanted to cover the conclusions of the discussion to remove the
> > blocking_pool. On the other hand, however, I want to support requirements
> > that need the blocking behavior.
> 
> I find it odd that /dev/random would be either a TRNG or not a TRNG
> depending on kernel configuration.  For the small fraction of users
> that actually want a TRNG, wouldn't it be better to have an interface
> that fails outright if the TRNG is not enabled?

Sure, I would have no concerns here.

> 
> --Andy


Ciao
Stephan



^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v24 11/12] LRNG - add SP800-90B compliant health tests
  2019-11-13  6:02       ` Alexander E. Patrakov
@ 2019-11-14  1:46         ` Stephan Müller
  0 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-14  1:46 UTC (permalink / raw)
  To: Alexander E. Patrakov
  Cc: Arnd Bergmann, Greg Kroah-Hartman, linux-crypto, LKML, Linux API,
	Eric W. Biederman, Ahmed S. Darwish, Theodore Y. Ts'o,
	Willy Tarreau, Matthew Garrett, Vito Caputo, Andreas Dilger,
	Jan Kara, Ray Strode, William Jon McCann, zhangjs,
	Andy Lutomirski, Florian Weimer, Lennart Poettering,
	Nicolai Stange, Peter, Matthias, Marcelo Henrique Cerri,
	Roman Drahtmueller, Neil Horman

Am Mittwoch, 13. November 2019, 07:02:40 CET schrieb Alexander E. Patrakov:

Hi Alexander,

> ср, 13 нояб. 2019 г. в 05:38, Stephan Müller <smueller@chronox.de>:
> > Am Dienstag, 12. November 2019, 20:58:32 CET schrieb Alexander E.
> > Patrakov:
> > 
> > Hi Alexander,
> > 
> > > > +config LRNG_HEALTH_TESTS
> > > > +   bool "Enable noise source online health tests"
> > > > +   help
> > > > +     The online health tests validate the noise source at
> > > > +     runtime for fatal errors. These tests include SP800-90B
> > > > +     compliant tests which are invoked if the system is booted
> > > > +     with fips=1. In case of fatal errors during active
> > > > +     SP800-90B tests, the issue is logged and the noise
> > > > +     data is discarded. These tests are required for full
> > > > +     compliance with SP800-90B.
> > > 
> > > How have you tested that these tests work at runtime? Maybe add some
> > > code under a new CONFIG item that depends on CONFIG_BROKEN that
> > > deliberately botches the RNG and triggers failures?
> > 
> > I am unable to find sensible information about CONFIG_BROKEN in the recent
> > kernel tree.
> > 
> > Do you happen to have a pointer on how that option is to be used?
> 
> This option is not used on its own. You create a new option,
> CONFIG_TEST_LRNG_FAILURE_MODE or something like that, and put your
> code under the ifdef guarded by that option. And then, to prevent
> ordinary users and allyesconfig from selecting it, in Kconfig you say:
> "depends on BROKEN". This way, the option becomes unselectable in
> menuconfig but still works as intended when added manually to .config
> (obviously, with the BROKEN dependency removed locally).
> 
> Definition:
> https://github.com/torvalds/linux/blob/9c7db5004280767566e91a33445bf93aa479
> ef02/init/Kconfig#L68 Example usage:
> https://github.com/torvalds/linux/blob/c87237110f2553b4200a8b3401a01198edfc
> f0d9/drivers/gpu/drm/i915/Kconfig.debug#L166

I added such support to the LRNG.

Thank you for your suggestion.
> 
> --
> Alexander E. Patrakov


Ciao
Stephan



^ permalink raw reply	[flat|nested] 162+ messages in thread

* [PATCH v25 00/12] /dev/random - a new approach with full SP800-90B
  2019-11-11 18:17 [PATCH v24 00/12] /dev/random - a new approach with full SP800-90B compliance Stephan Müller
                   ` (13 preceding siblings ...)
  2019-11-12 15:33 ` Andy Lutomirski
@ 2019-11-16  9:32 ` Stephan Müller
  2019-11-16  9:33   ` [PATCH v25 01/12] Linux Random Number Generator Stephan Müller
                     ` (12 more replies)
  14 siblings, 13 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-16  9:32 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

Hi,

The following patch set provides a different approach to /dev/random which is
called Linux Random Number Generator (LRNG) to collect entropy within the Linux
kernel. The main improvements compared to the existing /dev/random is to provide
sufficient entropy during boot time as well as in virtual environments and when
using SSDs. A secondary design goal is to limit the impact of the entropy
collection on massive parallel systems and also allow the use accelerated
cryptographic primitives. Also, all steps of the entropic data processing are
testable.

The LRNG patch set allows a user to select use of the existing /dev/random or
the LRNG during compile time. As the LRNG provides API and ABI compatible
interfaces to the existing /dev/random implementation, the user can freely chose
the RNG implementation without affecting kernel or user space operations.

This patch set provides early boot-time entropy which implies that no
additional flags to the getrandom(2) system call discussed recently on
the LKML is considered to be necessary. Yet, if additional flags are
introduced to cover special hardware, the LRNG implementation will also
provide them to be fully ABI and API compliant as already discussed on
LKML.

The LRNG is fully compliant to SP800-90B requirements and is shipped with a
full SP800-90B assessment and all required test tools. The existing /dev/random
implementation on the other hand has architectural limitations which
does not easily allow to bring the implementation in compliance with
SP800-90B. The key statement that causes concern is SP800-90B section
3.1.6. This section denies crediting entropy to multiple similar noise
sources. This section explicitly references different noise sources resting
on the timing of events and their derivatives (i.e. it is a direct complaint
to the existing existing /dev/random implementation). Therefore, SP800-90B
now denies the very issue mentioned in [1] with the existing /dev/random
implementation for a long time: crediting entropy to interrupts as well as
crediting entropy to derivatives of interrupts (HID and disk events). This is
not permissible with SP800-90B.

SP800-90B specifies various requirements for the noise source(s) that seed any
DRNG including SP800-90A DRBGs. In about a year from now, SP800-90B will be
mandated for all noise sources that provide entropy to DRBGs as part of a FIPS
140-[2|3] validation or other evaluation types. That means, if we there are no
solutions to comply with the requirements of SP800-90B found till one year
from now, any random number generation and ciphers based on random numbers
on Linux will be considered and treated as not applicable and delivering
no entropy! As /dev/urandom, getrandom(2) and /dev/random are the most
common and prevalent noise sources for DRNGs, all these DRNGs are affected.
This applies across the board for all validations of cryptography executing on
Linux (kernel and user space modules).

For users that are not interested in SP800-90B, the entire code for the
compliance as well as test interfaces can be deselected at compile time.

The design and implementation is driven by a set of goals described in [1]
that the LRNG completely implements. Furthermore, [1] includes the full
assessment of the SP800-90B compliance as well as a comparison with RNG
design suggestions of SP800-90C, and AIS20/31.

The LRNG provides a complete separation of the noise source maintenance
and the collection of entropy into an entropy pool from the post-processing
using a pseudo-random number generator. Different DRNGs are supported,
including:

* The LRNG can be compile-time enabled to replace the existing /dev/random
  implementation. When not selecting the LRNG at compile time (default), the
  existing /dev/random implementation is built.

* Built-in ChaCha20 DRNG which has no dependency to other kernel
  frameworks.

* SP800-90A DRBG using the kernel crypto API including its accelerated
  raw cipher implementations. This implies that the output of /dev/random,
  getrandom(2), /dev/urandom or get_random_bytes is fully compliant to
  SP800-90A.

* Arbitrary DRNGs registered with the kernel crypto API

* Full compliance with SP800-90B which covers the startup and runtime health
  tests mandated by SP800-90B as well as providing the test tools and test
  interfaces to obtain raw noise data securely. The test tools are provided at
  [1].

Booting the patch with the kernel command line option
"dyndbg=file drivers/char/lrng/* +p" generates logs indicating the operation
of the LRNG. Each log is pre-pended with "lrng".

The LRNG has a flexible design by allowing an easy replacement of the
deterministic random number generator component.

Compared to the existing /dev/random implementation, the compiled binary
is smaller when the LRNG is compiled with all options equal to the
existing /dev/random (i.e. only CONFIG_LRNG and
CONFIG_LRNG_TRNG_SUPPORT are set): random.o is 52.5 kBytes whereas
all LRNG object files are in 49 kBytes in size. The fully
SP800-90A/SP800-90B compliant binary code (CONFIG_LRNG,
CONFIG_LRNG_DRNG_SWITCH, CONFIG_LRNG_DRBG, CONFIG_LRNG_HEALTH_TESTS)
uses some 61 kBytes.

[1] http://www.chronox.de/lrng.html - If the patch is accepted, I would
be volunteering to convert the documentation into RST format and
contribute it to the Linux kernel documentation directory.

Changes (compared to the previous patch set):

* Remove of the boiler plate disclaimers as requested by Thomas Gleixner

* fix compile issues reported by kbuild: adding missing header files
  and turn large stack variable into a heap variable with lrng_testing.c

* fix patch descriptions as suggested by Florian Weimer and
  Alexander E. Patrakov

* remove stale comment in _lrng_sdrng_seed

* move blocking of /dev/random and getrandom(GRND_RANDOM) until LRNG is
  seeded to the interface handling code to simplify the code and to
  ensure the blocking is also enforced if the TRNG is not compiled.

* add BROKEN test support for SP800-90B adaptive proportion test and
  repetitive count test as suggested by Alexander E. Patrakov

A patch for adding power-up self tests is prepared but I did not want to add it
now to support code review of a code base with minimal changes. It will be
provided once the code review is completed. With this pending code, the
following tests are available:

* power-on self test: LFSR self test

* power-on self test: ChaCha20 DRNG self test

* power-on self test: time stamp array handling in lrng_sw_noise.c

* power-on self test: SP800-90A DRBG self test

* runtime test: raw noise source data collection, if enabled

* separate test: SP800-90B APT and RCT test enforcement validation if enabled

As a side node: With the switchable DRNG support offered in this patch set,
the following areas could be removed. As the existing /dev/random has no support
for switchable DRNGs, however, this is not yet feasible though.

* remove lrng_ready_list and all code around it in lrng_interfaces.c

* remove the kernel crypto API RNG API to avoid having two random number
  providing APIs - this would imply that all RNGs developed for this API would
  be converted to the LRNG interface

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>

Stephan Mueller (12):
  Linux Random Number Generator
  LRNG - allocate one SDRNG instance per NUMA node
  LRNG - /proc interface
  LRNG - add switchable DRNG support
  crypto: DRBG - externalize DRBG functions for LRNG
  LRNG - add SP800-90A DRBG extension
  LRNG - add kernel crypto API PRNG extension
  crypto: provide access to a static Jitter RNG state
  LRNG - add Jitter RNG fast noise source
  LRNG - add TRNG support
  LRNG - add SP800-90B compliant health tests
  LRNG - add interface for gathering of raw entropy

 MAINTAINERS                         |   7 +
 crypto/drbg.c                       |  16 +-
 crypto/jitterentropy.c              |  23 +
 drivers/char/Kconfig                |   2 +
 drivers/char/Makefile               |   9 +-
 drivers/char/lrng/Kconfig           | 188 ++++++++
 drivers/char/lrng/Makefile          |  19 +
 drivers/char/lrng/lrng_archrandom.c |  92 ++++
 drivers/char/lrng/lrng_aux.c        | 148 +++++++
 drivers/char/lrng/lrng_chacha20.c   | 328 ++++++++++++++
 drivers/char/lrng/lrng_drbg.c       | 261 +++++++++++
 drivers/char/lrng/lrng_health.c     | 409 +++++++++++++++++
 drivers/char/lrng/lrng_interfaces.c | 647 +++++++++++++++++++++++++++
 drivers/char/lrng/lrng_internal.h   | 309 +++++++++++++
 drivers/char/lrng/lrng_jent.c       |  88 ++++
 drivers/char/lrng/lrng_kcapi.c      | 328 ++++++++++++++
 drivers/char/lrng/lrng_numa.c       | 101 +++++
 drivers/char/lrng/lrng_pool.c       | 660 ++++++++++++++++++++++++++++
 drivers/char/lrng/lrng_proc.c       | 179 ++++++++
 drivers/char/lrng/lrng_sdrng.c      | 436 ++++++++++++++++++
 drivers/char/lrng/lrng_sw_noise.c   | 144 ++++++
 drivers/char/lrng/lrng_switch.c     | 185 ++++++++
 drivers/char/lrng/lrng_testing.c    | 324 ++++++++++++++
 drivers/char/lrng/lrng_trng.c       | 283 ++++++++++++
 include/crypto/drbg.h               |   7 +
 include/linux/lrng.h                |  83 ++++
 26 files changed, 5269 insertions(+), 7 deletions(-)
 create mode 100644 drivers/char/lrng/Kconfig
 create mode 100644 drivers/char/lrng/Makefile
 create mode 100644 drivers/char/lrng/lrng_archrandom.c
 create mode 100644 drivers/char/lrng/lrng_aux.c
 create mode 100644 drivers/char/lrng/lrng_chacha20.c
 create mode 100644 drivers/char/lrng/lrng_drbg.c
 create mode 100644 drivers/char/lrng/lrng_health.c
 create mode 100644 drivers/char/lrng/lrng_interfaces.c
 create mode 100644 drivers/char/lrng/lrng_internal.h
 create mode 100644 drivers/char/lrng/lrng_jent.c
 create mode 100644 drivers/char/lrng/lrng_kcapi.c
 create mode 100644 drivers/char/lrng/lrng_numa.c
 create mode 100644 drivers/char/lrng/lrng_pool.c
 create mode 100644 drivers/char/lrng/lrng_proc.c
 create mode 100644 drivers/char/lrng/lrng_sdrng.c
 create mode 100644 drivers/char/lrng/lrng_sw_noise.c
 create mode 100644 drivers/char/lrng/lrng_switch.c
 create mode 100644 drivers/char/lrng/lrng_testing.c
 create mode 100644 drivers/char/lrng/lrng_trng.c
 create mode 100644 include/linux/lrng.h

-- 
2.23.0





^ permalink raw reply	[flat|nested] 162+ messages in thread

* [PATCH v25 01/12] Linux Random Number Generator
  2019-11-16  9:32 ` [PATCH v25 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
@ 2019-11-16  9:33   ` Stephan Müller
  2019-11-16 11:25     ` Thomas Gleixner
  2019-11-16 18:13     ` Nicolai Stange
  2019-11-16  9:33   ` [PATCH v25 02/12] LRNG - allocate one SDRNG instance per NUMA node Stephan Müller
                     ` (11 subsequent siblings)
  12 siblings, 2 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-16  9:33 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

In an effort to provide a flexible implementation for a random number
generator that also delivers entropy during early boot time, allows
replacement of the deterministic random number generation mechanism,
implement the various components in separate code for easier
maintenance, and provide compliance to SP800-90[A|B|C], introduce
the Linux Random Number Generator (LRNG) framework.

The general design is as follows. Additional implementation details
are given in [1]. The LRNG consists of the following components:

1. The LRNG may contain a True Random Number Generator (TRNG). The
TRNG is a deterministic random number generator that is operated as
a true random number generator. Using SP800-90A terminology, the
TRNG is a DRBG with prediction resistance. The TRNG has a behavior
similar to SP800-90A's concept of prediction resistance by only
generating output when it is re-seeded with an equal amount of
entropy. Every time a caller requests random numbers, the TRNG
must be re-seeded with at least that amount of entropy from its noise
sources. During boot time, the TRNG is not yet operated with
prediction resistance. As the external interfaces to the TRNG to
obtain random numbers start to be accessible after boot time
completes, random numbers generated via these interfaces always
access the TRNG that is operated with prediction resistance.

2. The LRNG implements a secondary DRNG. The secondary DRNG always
generates the requested amount of output. When using the SP800-90A
terminology it operates without prediction resistance. The secondary
DRNG maintains a counter of how many bytes were generated since last
re-seed and a timer of the elapsed time since last re-seed. If either
the counter or the timer reaches a threshold, the secondary DRNG is
seeded from the TRNG.

In case the Linux kernel detects a NUMA system, one secondary DRNG
instance per NUMA node is maintained.

3. The TRNG is seeded by concatenating the data from the
following sources:

(a) the output of the entropy pool,

(b) the Jitter RNG if available and enabled, and

(c) the CPU-based noise source such as Intel RDRAND if available and
enabled.

The entropy estimate of the data of all noise sources are added to
form the entropy estimate of the data used to seed the TRNG with.
The LRNG ensures, however, that the TRNG after seeding is at
maximum the security strength of the TRNG.

The LRNG is designed such that none of these noise sources can dominate
the other noise sources to provide seed data to the TRNG during
boot time due to the following:

(a) During boot time, the amount of received interrupts are the trigger
points to (re)seed the TRNG.

(b) At runtime, the caller requesting random numbers from the primary
TRNG drives the reseeding where always as much entropy as available is
used to reseed the TRNG.

4. The entropy pool accumulates entropy obtained from certain events,
which will henceforth be collectively called "slow noise sources".
The entropy pool collects noise data from slow noise sources. Any data
received by the LRNG from the slow noise sources is inserted into the
entropy pool using an LFSR with a primitive and irreducible polynomial.
The following sources of entropy are used:

 (a) When an interrupt occurs, the high-resolution time stamp is mixed
into the LFSR. This time stamp is credited with heuristically implied
entropy.

 (b) HID event data like the key stroke or the mouse coordinates are
mixed into the LFSR. This data is not credited with entropy by the LRNG.

 (c) Device drivers may provide data that is mixed into the LFSR. This
data is not credited with entropy by the LRNG.

 (d) After the entropy pool is ``read'' by the TRNG, the data
used to seed the TRNG is mixed back into the entropy pool to
stir the pool. This data is not credited with entropy by the LRNG.

Any data provided from user space by either writing to /dev/random,
/dev/urandom or the IOCTL of RNDADDENTROPY on both device files
are always injected into the entropy pool.

In addition, when a hardware random number generator covered by the
Linux kernel HW generator framework wants to deliver random numbers,
it is injected into the entropy pool as well. HW generator noise source
is handled separately from the other noise source due to the fact that
the HW generator framework may decide by itself when to deliver data
whereas the other noise sources always requested for data driven by the
LRNG operation. Similarly any user space provided data is inserted into
the entropy pool.

When the TRNG requires data from the entropy pool, the entire
entropy pool is processed with an SP800-90A section 10.3.1 compliant
hash_df function to generate random numbers.

To speed up the interrupt handling code of the LRNG, the time stamp
collected for an interrupt event is truncated to the 8 least
significant bits. 64 truncated time stamps are concatenated and then
jointly inserted into the LFSR. During boot time, until the fully seeded
stage is reached, each time stamp with its 32 least significant bits is
inserted into the LFSR at the time of arrival.

The LRNG allows the TRNG and secondary DRNG mechanism to be changed
at runtime. Per default, a ChaCha20-based DRNG is used. The ChaCha20-DRNG
implemented for the LRNG is also provided as a stand-alone user space
deterministic random number generator. The LRNG also offers an
SP800-90A DRBG based on the Linux kernel crypto API DRBG implementation.

The DRNG allows two methods of obtaining random data:

* For users requiring random numbers from a seeded and frequently reseeded
secondary DRNG, such as the /dev/urandom, the getrandom system call or
the in-kernel get_random_bytes function, the secondary DRNG is accessed
directly by invoking its generate function. This generate function
complies with the generate function discussed in SP800-90A.

* Users requiring random data that contains information theoretical
entropy, such as for seeding other DRNGs also use the TRNG's
generate function via the /dev/random device file and the getrandom
system call when invoked with GRND_RANDOM. The difference to the
/dev/urandom handling is that:

 1. each TRNG generate request is limited to the amount of entropy
the of the DRNG was seeded with, and

 2. each TRNG generate request is preceded by a reseeding of the
DRNG to implement a TRNG / a DRNG with prediction resistance.

The processing of entropic data from the noise source before injecting
them into the TRNG is performed with the following mathematical
operations:

1. LFSR: The 8 least significant bits of the time stamp data received
from the interrupts are processed with an LFSR. That LFSR is implemented
identically to the LSFR used in the existing /dev/random implementation
except that it is capable of processing an entire word and that a
different polynomial is used. The reason for the different polynomial
is performance in a performance sensitive code section, the interrupt
handler. The chosen polynomials have 4 taps. Also, this LFSR-approach
is used in the OpenBSD /dev/random equivalent.

2. Concatenation: The temporary seed buffer used to seed the TRNG is
a concatenation of parts of the entropy pool data, and the CPU noise
source output.

The TRNG always tries to seed itself with 256 bits of entropy,
except during boot. In any case, if the noise sources cannot deliver
that amount, the available entropy is used and the TRNG keeps
track on how much entropy it was seeded with. The entropy implied by
the LRNG available in the entropy pool may be too conservative.
To ensure that during boot time all available entropy from the entropy
pool is transferred to the TRNG, the hash_df function always
generates 256 data bits during boot to seed the TRNG. Yet, the
TRNG entropy estimate is only increased by the amount of entropy the
LRNG assumes to be present in that data. During boot, the TRNG
is seeded as follows:

1. The DRNG is reseeded from the entropy pool and potentially the fast
noise sources if the entropy pool has collected at least 32 bits of
entropy from the interrupt noise source. The goal of this step is to
ensure that the primary and secondary DRNG receive some initial entropy
as early as possible. In addition it receives the entropy available from
the fast noise sources.

2. The DRNG is reseeded from the entropy pool and potentially the fast
noise sources if all noise sources collectively can provide at least
128 bits of entropy.

3. The DRNG is reseeded from the entropy pool and potentially the fast
noise sources if all noise sources collectivel can provide at least 256
bits.

At the time of the reseeding steps, the DRNG requests as much entropy as
is available in order to skip certain steps and reach the seeding level
of 256 bits. This may imply that one or more of the aforementioned steps
are skipped.

In all listed steps, the secondary DRNG is (re)seeded with a number of
random bytes from the TRNG that is equal to the amount of
entropy the TRNG was seeded with. This means that when the
TRNG is seeded with 128 or 256 bits of entropy, the secondary
DRNG is seeded with that amount of entropy as well. There is only one
exception to that rule: during initialization before the seed level of
128 bits is reached, a random number with 128 bit is generated by the
TRNG to seed the secondary DRNG.

Before the TRNG is seeded with 256 bits of entropy in step 3,
requests of random data from /dev/random are not processed.

At runtime, the TRNG delivers only random bytes equal to the
entropy amount it was seeded with. E.g. if the TRNG was seeded
with 128 bits of entropy, it will return only 128 bits of random data.
Subsequent requests for random data are only fulfilled after a
reseeding operation of the TRNG.

The TRNG will always require that all entropy sources collectively
can deliver at least as many entropy bits as configured with
/proc/sys/kernel/random/read_wakeup_threshold, i.e. per default 129 bits
(128 bits of entropy for seeding plus one bit of entropy that is lost
with the post processing as defined in SP800-90B).

The secondary DRNG operates as deterministic random number generator with
the following properties:

* The maximum number of random bytes that can be generated with one
DRNG generate operation is limited to 4096 bytes. When longer random
numbers are requested, multiple DRNG generate operations are performed.
The ChaCha20 DRNG as well as the SP800-90A DRBGs implement an update of
their state after completing a generate request for backtracking
resistance.

* The secondary DRNG is reseeded with whatever entropy is available –
in the worst case where no additional entropy can be provided by the
noise sources, the DRNG is not re-seeded and continues its operation
to try to reseed again after again the expiry of one of these thresholds:

 - If the last reseeding of the secondary DRNG is more than 600 seconds
   ago, or

 - 2^20 DRNG generate operations are performed, whatever comes first, or

 - the secondary DRNG is forced to reseed before the next generation of
   random numbers if data has been injected into the LRNG by writing data
   into /dev/random or /dev/urandom.

The chosen values prevent high-volume requests from user space to cause
frequent reseeding operations which drag down the performance of the
DRNG.

When the secondary DRNG requests a reseeding from the TRNG and
the TRNG pulls from the entropy pool, an emergency entropy level
of 512 bits of entropy is left in the entropy pool. This emergency
entropy is provided to serve /dev/random even while /dev/urandom is
stressed.

With the automatic reseeding after 600 seconds, the LRNG is triggered
to reseed itself before the first request after a suspend that put the
hardware to sleep for longer than 600 seconds.

The TRNG may not be compiled. In this case, the aforementioned
statements covering the TRNG are not applicable. The secondary DRNG is
seeded directly from the entropy pool just like the TRNG would have been
seeded.

The LRNG has the following properties:

* internal noise source: interrupts timing with fast boot time seeding

* 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().

* lockless LFSR to collect raw entropy

* use of standalone ChaCha20 based RNG with the option to use a
  different DRNG selectable at compile time

* "atomic" seeding of secondary DRBG to ensure full entropy transport

* instantiate one DRNG per NUMA node

* support for runtime switchable output DRNGs

* support for TRNG deactivation: The LRNG supports the compile-time
deactivation of the TRNG (i.e. the blocking behavior of /dev/random).
If deactivated, /dev/random operates like getrandom(2). This is
intended to cover the recent discussions about removing the
blocking_pool from the existing random.c.

* use of only well-defined entropy-preserving operations to collect,
compress and forward entropy: concatenation, LFSR, SP800-90A hash_df
function

* compile-time selectable entropy pool size: the choice also
uses the applicable LFSR polynomial to maintain the entropy pool
size

Further details including the rationale for the design choices and
properties of the LRNG together with testing is provided at [1].
In addition, the documentation explains the conducted regression
tests to verify that the LRNG is API and ABI compatible with the
existing /dev/random implementation.

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

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Mathematical aspects Reviewed-by: "Peter, Matthias" <matthias.peter@bsi.bund.de>
Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 MAINTAINERS                         |   7 +
 drivers/char/Kconfig                |   2 +
 drivers/char/Makefile               |   9 +-
 drivers/char/lrng/Kconfig           |  55 +++
 drivers/char/lrng/Makefile          |   9 +
 drivers/char/lrng/lrng_archrandom.c |  92 ++++
 drivers/char/lrng/lrng_aux.c        | 148 +++++++
 drivers/char/lrng/lrng_chacha20.c   | 328 ++++++++++++++
 drivers/char/lrng/lrng_interfaces.c | 648 +++++++++++++++++++++++++++
 drivers/char/lrng/lrng_internal.h   | 300 +++++++++++++
 drivers/char/lrng/lrng_pool.c       | 660 ++++++++++++++++++++++++++++
 drivers/char/lrng/lrng_sdrng.c      | 436 ++++++++++++++++++
 drivers/char/lrng/lrng_sw_noise.c   | 144 ++++++
 include/linux/lrng.h                |  83 ++++
 14 files changed, 2920 insertions(+), 1 deletion(-)
 create mode 100644 drivers/char/lrng/Kconfig
 create mode 100644 drivers/char/lrng/Makefile
 create mode 100644 drivers/char/lrng/lrng_archrandom.c
 create mode 100644 drivers/char/lrng/lrng_aux.c
 create mode 100644 drivers/char/lrng/lrng_chacha20.c
 create mode 100644 drivers/char/lrng/lrng_interfaces.c
 create mode 100644 drivers/char/lrng/lrng_internal.h
 create mode 100644 drivers/char/lrng/lrng_pool.c
 create mode 100644 drivers/char/lrng/lrng_sdrng.c
 create mode 100644 drivers/char/lrng/lrng_sw_noise.c
 create mode 100644 include/linux/lrng.h

diff --git a/MAINTAINERS b/MAINTAINERS
index cba1095547fd..7232989d3a1c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9488,6 +9488,13 @@ F:	Documentation/core-api/atomic_ops.rst
 F:	Documentation/core-api/refcount-vs-atomic.rst
 F:	Documentation/memory-barriers.txt
 
+LINUX RANDOM NUMBER GENERATOR (LRNG) DRIVER
+M:	Stephan Mueller <smueller@chronox.de>
+S:	Maintained
+W:	https://www.chronox.de/lrng.html
+F:	drivers/char/lrng/*
+F:	include/linux/lrng.h
+
 LIS3LV02D ACCELEROMETER DRIVER
 M:	Eric Piel <eric.piel@tremplin-utc.net>
 S:	Maintained
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index df0fc997dc3e..cebb3a62c2ca 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -535,6 +535,8 @@ config ADI
 	  and SSM (Silicon Secured Memory).  Intended consumers of this
 	  driver include crash and makedumpfile.
 
+source "drivers/char/lrng/Kconfig"
+
 endmenu
 
 config RANDOM_TRUST_CPU
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 7c5ea6f9df14..46ede09fd6d3 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -3,7 +3,14 @@
 # Makefile for the kernel character device drivers.
 #
 
-obj-y				+= mem.o random.o
+obj-y				+= mem.o
+
+ifeq ($(CONFIG_LRNG),y)
+  obj-y				+= lrng/
+else
+  obj-y				+= random.o
+endif
+
 obj-$(CONFIG_TTY_PRINTK)	+= ttyprintk.o
 obj-y				+= misc.o
 obj-$(CONFIG_ATARI_DSP56K)	+= dsp56k.o
diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
new file mode 100644
index 000000000000..1ba10fd421f3
--- /dev/null
+++ b/drivers/char/lrng/Kconfig
@@ -0,0 +1,55 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Linux Random Number Generator configuration
+#
+
+menuconfig LRNG
+	bool "Linux Random Number Generator"
+	help
+	  The Linux Random Number Generator (LRNG) is the replacement
+	  of the existing /dev/random provided with drivers/char/random.c.
+	  It generates entropy from different noise sources and
+	  delivers significant entropy during boot.
+
+if LRNG
+
+choice
+	prompt "LRNG Entropy Pool Size"
+	default LRNG_POOL_SIZE_4096
+	help
+	  Select the size of the LRNG entropy pool. The size of the
+	  entropy pool is relevant for the amount of entropy that
+	  the LRNG can maintain as a maximum. The larger the size
+	  of the entropy pool is the more entropy can be maintained
+	  but the less often older entropic values are overwritten
+	  with new entropy.
+
+	config LRNG_POOL_SIZE_4096
+		bool "4096 bits (default)"
+
+	config LRNG_POOL_SIZE_8192
+		bool "8192 bits"
+
+	config LRNG_POOL_SIZE_16384
+		bool "16384 bits"
+
+	config LRNG_POOL_SIZE_32768
+		bool "32768 bits"
+
+	config LRNG_POOL_SIZE_65536
+		bool "65536 bits"
+
+	config LRNG_POOL_SIZE_131072
+		bool "131072 bits"
+endchoice
+
+config LRNG_POOL_SIZE
+	int
+	default 0 if LRNG_POOL_SIZE_4096
+	default 1 if LRNG_POOL_SIZE_8192
+	default 2 if LRNG_POOL_SIZE_16384
+	default 3 if LRNG_POOL_SIZE_32768
+	default 4 if LRNG_POOL_SIZE_65536
+	default 5 if LRNG_POOL_SIZE_131072
+
+endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
new file mode 100644
index 000000000000..2761623715d2
--- /dev/null
+++ b/drivers/char/lrng/Makefile
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for the Linux Random Number Generator.
+#
+
+obj-y				+= lrng_pool.o lrng_aux.o \
+				   lrng_sw_noise.o lrng_archrandom.o \
+				   lrng_sdrng.o lrng_chacha20.o \
+				   lrng_interfaces.o \
diff --git a/drivers/char/lrng/lrng_archrandom.c b/drivers/char/lrng/lrng_archrandom.c
new file mode 100644
index 000000000000..e03dc57c56f6
--- /dev/null
+++ b/drivers/char/lrng/lrng_archrandom.c
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG Fast Noise Source: CPU-based noise source
+ *
+ * Copyright (C) 2016 - 2019, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/random.h>
+
+#include "lrng_internal.h"
+
+/*
+ * Estimated entropy of data is a 32th of LRNG_DRNG_SECURITY_STRENGTH_BITS.
+ * As we have no ability to review the implementation of those noise sources,
+ * it is prudent to have a conservative estimate here.
+ */
+#define LRNG_ARCHRANDOM_DEFAULT_STRENGTH (LRNG_DRNG_SECURITY_STRENGTH_BITS>>5)
+#define LRNG_ARCHRANDOM_TRUST_CPU_STRENGTH LRNG_DRNG_SECURITY_STRENGTH_BITS
+#ifdef CONFIG_RANDOM_TRUST_CPU
+static u32 archrandom = LRNG_ARCHRANDOM_TRUST_CPU_STRENGTH;
+#else
+static u32 archrandom = LRNG_ARCHRANDOM_DEFAULT_STRENGTH;
+#endif
+module_param(archrandom, uint, 0644);
+MODULE_PARM_DESC(archrandom, "Entropy in bits of 256 data bits from CPU noise "
+			     "source (e.g. RDRAND)");
+
+static int __init lrng_parse_trust_cpu(char *arg)
+{
+	int ret;
+	bool trust_cpu = false;
+
+	ret = kstrtobool(arg, &trust_cpu);
+	if (ret)
+		return ret;
+
+	if (trust_cpu)
+		archrandom = LRNG_ARCHRANDOM_TRUST_CPU_STRENGTH;
+	else
+		archrandom = LRNG_ARCHRANDOM_DEFAULT_STRENGTH;
+
+	return 0;
+}
+early_param("random.trust_cpu", lrng_parse_trust_cpu);
+
+/**
+ * Get CPU noise source entropy
+ *
+ * @outbuf: buffer to store entropy of size LRNG_DRNG_SECURITY_STRENGTH_BYTES
+ * @return: > 0 on success where value provides the added entropy in bits
+ *	    0 if no fast source was available
+ */
+u32 lrng_get_arch(u8 *outbuf)
+{
+	u32 i, ent_bits = archrandom;
+
+	/* operate on full blocks */
+	BUILD_BUG_ON(LRNG_DRNG_SECURITY_STRENGTH_BYTES % sizeof(unsigned long));
+	/* ensure we have aligned buffers */
+	BUILD_BUG_ON(LRNG_KCAPI_ALIGN % sizeof(unsigned long));
+
+	if (!ent_bits)
+		return 0;
+
+	for (i = 0; i < LRNG_DRNG_SECURITY_STRENGTH_BYTES;
+	     i += sizeof(unsigned long)) {
+		if (!arch_get_random_seed_long((unsigned long *)(outbuf + i)) &&
+		    !arch_get_random_long((unsigned long *)(outbuf + i))) {
+			archrandom = 0;
+			return 0;
+		}
+	}
+
+	/* Obtain entropy statement -- cap entropy to buffer size in bits */
+	ent_bits = min_t(u32, ent_bits, LRNG_DRNG_SECURITY_STRENGTH_BITS);
+	pr_debug("obtained %u bits of entropy from CPU RNG noise source\n",
+		 ent_bits);
+	return ent_bits;
+}
+
+u32 lrng_slow_noise_req_entropy(u32 required_entropy_bits)
+{
+	u32 arch_ent_bits = min_t(u32, archrandom,
+				  LRNG_DRNG_SECURITY_STRENGTH_BITS);
+	u32 fast_noise_entropy = arch_ent_bits + lrng_jent_entropylevel();
+
+	if (fast_noise_entropy > required_entropy_bits)
+		return 0;
+	return (required_entropy_bits - fast_noise_entropy);
+}
diff --git a/drivers/char/lrng/lrng_aux.c b/drivers/char/lrng/lrng_aux.c
new file mode 100644
index 000000000000..de2904523ea2
--- /dev/null
+++ b/drivers/char/lrng/lrng_aux.c
@@ -0,0 +1,148 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG auxiliary interfaces
+ *
+ * Copyright (C) 2019 Stephan Mueller <smueller@chronox.de>
+ * Copyright (C) 2017 Jason A. Donenfeld <Jason@zx2c4.com>. All
+ * Rights Reserved.
+ * Copyright (C) 2016 Jason Cooper <jason@lakedaemon.net>
+ */
+
+#include <linux/mm.h>
+#include <linux/random.h>
+
+#include "lrng_internal.h"
+
+struct batched_entropy {
+	union {
+		u64 entropy_u64[LRNG_DRNG_BLOCKSIZE / sizeof(u64)];
+		u32 entropy_u32[LRNG_DRNG_BLOCKSIZE / sizeof(u32)];
+	};
+	unsigned int position;
+	spinlock_t batch_lock;
+};
+
+/*
+ * Get a random word for internal kernel use only. The quality of the random
+ * number is either as good as RDRAND or as good as /dev/urandom, with the
+ * goal of being quite fast and not depleting entropy.
+ */
+static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_u64) = {
+	.batch_lock	= __SPIN_LOCK_UNLOCKED(batched_entropy_u64.lock),
+};
+
+u64 get_random_u64(void)
+{
+	u64 ret;
+	unsigned long flags;
+	struct batched_entropy *batch;
+
+#if BITS_PER_LONG == 64
+	if (arch_get_random_long((unsigned long *)&ret))
+		return ret;
+#else
+	if (arch_get_random_long((unsigned long *)&ret) &&
+	    arch_get_random_long((unsigned long *)&ret + 1))
+		return ret;
+#endif
+
+	lrng_debug_report_seedlevel("get_random_u64");
+
+	batch = raw_cpu_ptr(&batched_entropy_u64);
+	spin_lock_irqsave(&batch->batch_lock, flags);
+	if (batch->position % ARRAY_SIZE(batch->entropy_u64) == 0) {
+		lrng_sdrng_get_atomic((u8 *)batch->entropy_u64,
+				      LRNG_DRNG_BLOCKSIZE);
+		batch->position = 0;
+	}
+	ret = batch->entropy_u64[batch->position++];
+	spin_unlock_irqrestore(&batch->batch_lock, flags);
+	return ret;
+}
+EXPORT_SYMBOL(get_random_u64);
+
+static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_u32) = {
+	.batch_lock	= __SPIN_LOCK_UNLOCKED(batched_entropy_u32.lock),
+};
+
+u32 get_random_u32(void)
+{
+	u32 ret;
+	unsigned long flags;
+	struct batched_entropy *batch;
+
+	if (arch_get_random_int(&ret))
+		return ret;
+
+	lrng_debug_report_seedlevel("get_random_u32");
+
+	batch = raw_cpu_ptr(&batched_entropy_u32);
+	spin_lock_irqsave(&batch->batch_lock, flags);
+	if (batch->position % ARRAY_SIZE(batch->entropy_u32) == 0) {
+		lrng_sdrng_get_atomic((u8 *)batch->entropy_u32,
+				      LRNG_DRNG_BLOCKSIZE);
+		batch->position = 0;
+	}
+	ret = batch->entropy_u32[batch->position++];
+	spin_unlock_irqrestore(&batch->batch_lock, flags);
+	return ret;
+}
+EXPORT_SYMBOL(get_random_u32);
+
+/*
+ * It's important to invalidate all potential batched entropy that might
+ * be stored before the crng is initialized, which we can do lazily by
+ * simply resetting the counter to zero so that it's re-extracted on the
+ * next usage.
+ */
+void invalidate_batched_entropy(void)
+{
+	int cpu;
+	unsigned long flags;
+
+	for_each_possible_cpu(cpu) {
+		struct batched_entropy *batched_entropy;
+
+		batched_entropy = per_cpu_ptr(&batched_entropy_u32, cpu);
+		spin_lock_irqsave(&batched_entropy->batch_lock, flags);
+		batched_entropy->position = 0;
+		spin_unlock(&batched_entropy->batch_lock);
+
+		batched_entropy = per_cpu_ptr(&batched_entropy_u64, cpu);
+		spin_lock(&batched_entropy->batch_lock);
+		batched_entropy->position = 0;
+		spin_unlock_irqrestore(&batched_entropy->batch_lock, flags);
+	}
+}
+
+/**
+ * randomize_page - Generate a random, page aligned address
+ * @start:	The smallest acceptable address the caller will take.
+ * @range:	The size of the area, starting at @start, within which the
+ *		random address must fall.
+ *
+ * If @start + @range would overflow, @range is capped.
+ *
+ * NOTE: Historical use of randomize_range, which this replaces, presumed that
+ * @start was already page aligned.  We now align it regardless.
+ *
+ * Return: A page aligned address within [start, start + range).  On error,
+ * @start is returned.
+ */
+unsigned long randomize_page(unsigned long start, unsigned long range)
+{
+	if (!PAGE_ALIGNED(start)) {
+		range -= PAGE_ALIGN(start) - start;
+		start = PAGE_ALIGN(start);
+	}
+
+	if (start > ULONG_MAX - range)
+		range = ULONG_MAX - start;
+
+	range >>= PAGE_SHIFT;
+
+	if (range == 0)
+		return start;
+
+	return start + (get_random_long() % range << PAGE_SHIFT);
+}
diff --git a/drivers/char/lrng/lrng_chacha20.c b/drivers/char/lrng/lrng_chacha20.c
new file mode 100644
index 000000000000..52efe2dc9c2b
--- /dev/null
+++ b/drivers/char/lrng/lrng_chacha20.c
@@ -0,0 +1,328 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * Backend for the LRNG providing the cryptographic primitives using
+ * ChaCha20 cipher implementations.
+ *
+ * Copyright (C) 2016 - 2019, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <crypto/chacha.h>
+#include <linux/cryptohash.h>
+#include <linux/lrng.h>
+#include <linux/random.h>
+
+#include "lrng_internal.h"
+
+/******************************* ChaCha20 DRNG *******************************/
+
+/* State according to RFC 7539 section 2.3 */
+struct chacha20_block {
+	u32 constants[4];
+#define CHACHA_KEY_SIZE_WORDS (CHACHA_KEY_SIZE / sizeof(u32))
+	union {
+		u32 u[CHACHA_KEY_SIZE_WORDS];
+		u8  b[CHACHA_KEY_SIZE];
+	} key;
+	u32 counter;
+	u32 nonce[3];
+};
+
+#define CHACHA_BLOCK_WORDS	(CHACHA_BLOCK_SIZE / sizeof(u32))
+
+struct chacha20_state {
+	struct chacha20_block block;
+};
+
+/*
+ * Have two static memory blocks for two ChaCha20 DRNG instances (the primary
+ * and the secondary DRNG) to avoid calling kmalloc too early in the boot cycle.
+ * for subsequent allocation requests, such as per-NUMA-node DRNG instances,
+ * kmalloc will be used.
+ */
+struct chacha20_state primary_chacha20;
+struct chacha20_state secondary_chacha20;
+
+/**
+ * Update of the ChaCha20 state by either using an unused buffer part or by
+ * generating one ChaCha20 block which is half of the state of the ChaCha20.
+ * The block is XORed into the key part of the state. This shall ensure
+ * backtracking resistance as well as a proper mix of the ChaCha20 state once
+ * the key is injected.
+ */
+static void lrng_chacha20_update(struct chacha20_state *chacha20_state,
+				 u32 *buf, u32 used_words)
+{
+	struct chacha20_block *chacha20 = &chacha20_state->block;
+	u32 i, tmp[CHACHA_BLOCK_WORDS];
+
+	BUILD_BUG_ON(sizeof(struct chacha20_block) != CHACHA_BLOCK_SIZE);
+	BUILD_BUG_ON(CHACHA_BLOCK_SIZE != 2 * CHACHA_KEY_SIZE);
+
+	if (used_words > CHACHA_KEY_SIZE_WORDS) {
+		chacha20_block(&chacha20->constants[0], (u8 *)tmp);
+		for (i = 0; i < CHACHA_KEY_SIZE_WORDS; i++)
+			chacha20->key.u[i] ^= tmp[i];
+		memzero_explicit(tmp, sizeof(tmp));
+	} else {
+		for (i = 0; i < CHACHA_KEY_SIZE_WORDS; i++)
+			chacha20->key.u[i] ^= buf[i + used_words];
+	}
+
+	/* Deterministic increment of nonce as required in RFC 7539 chapter 4 */
+	chacha20->nonce[0]++;
+	if (chacha20->nonce[0] == 0)
+		chacha20->nonce[1]++;
+	if (chacha20->nonce[1] == 0)
+		chacha20->nonce[2]++;
+
+	/* Leave counter untouched as it is start value is undefined in RFC */
+}
+
+/**
+ * Seed the ChaCha20 DRNG by injecting the input data into the key part of
+ * the ChaCha20 state. If the input data is longer than the ChaCha20 key size,
+ * perform a ChaCha20 operation after processing of key size input data.
+ * This operation shall spread out the entropy into the ChaCha20 state before
+ * new entropy is injected into the key part.
+ */
+static int lrng_cc20_drng_seed_helper(void *drng, const u8 *inbuf, u32 inbuflen)
+{
+	struct chacha20_state *chacha20_state = (struct chacha20_state *)drng;
+	struct chacha20_block *chacha20 = &chacha20_state->block;
+
+	while (inbuflen) {
+		u32 i, todo = min_t(u32, inbuflen, CHACHA_KEY_SIZE);
+
+		for (i = 0; i < todo; i++)
+			chacha20->key.b[i] ^= inbuf[i];
+
+		/* Break potential dependencies between the inbuf key blocks */
+		lrng_chacha20_update(chacha20_state, NULL,
+				     CHACHA_BLOCK_WORDS);
+		inbuf += todo;
+		inbuflen -= todo;
+	}
+
+	return 0;
+}
+
+/**
+ * Chacha20 DRNG generation of random numbers: the stream output of ChaCha20
+ * is the random number. After the completion of the generation of the
+ * stream, the entire ChaCha20 state is updated.
+ *
+ * Note, as the ChaCha20 implements a 32 bit counter, we must ensure
+ * that this function is only invoked for at most 2^32 - 1 ChaCha20 blocks
+ * before a reseed or an update happens. This is ensured by the variable
+ * outbuflen which is a 32 bit integer defining the number of bytes to be
+ * generated by the ChaCha20 DRNG. At the end of this function, an update
+ * operation is invoked which implies that the 32 bit counter will never be
+ * overflown in this implementation.
+ */
+static int lrng_cc20_drng_generate_helper(void *drng, u8 *outbuf, u32 outbuflen)
+{
+	struct chacha20_state *chacha20_state = (struct chacha20_state *)drng;
+	struct chacha20_block *chacha20 = &chacha20_state->block;
+	u32 aligned_buf[CHACHA_BLOCK_WORDS], ret = outbuflen,
+	    used = CHACHA_BLOCK_WORDS;
+	int zeroize_buf = 0;
+
+	while (outbuflen >= CHACHA_BLOCK_SIZE) {
+		chacha20_block(&chacha20->constants[0], outbuf);
+		outbuf += CHACHA_BLOCK_SIZE;
+		outbuflen -= CHACHA_BLOCK_SIZE;
+	}
+
+	if (outbuflen) {
+		chacha20_block(&chacha20->constants[0], (u8 *)aligned_buf);
+		memcpy(outbuf, aligned_buf, outbuflen);
+		used = ((outbuflen + sizeof(aligned_buf[0]) - 1) /
+			sizeof(aligned_buf[0]));
+		zeroize_buf = 1;
+	}
+
+	lrng_chacha20_update(chacha20_state, aligned_buf, used);
+
+	if (zeroize_buf)
+		memzero_explicit(aligned_buf, sizeof(aligned_buf));
+
+	return ret;
+}
+
+/**
+ * ChaCha20 DRNG that provides full strength, i.e. the output is capable
+ * of transporting 1 bit of entropy per data bit, provided the DRNG was
+ * seeded with 256 bits of entropy. This is achieved by folding the ChaCha20
+ * block output of 512 bits in half using XOR.
+ *
+ * Other than the output handling, the implementation is conceptually
+ * identical to lrng_drng_generate_helper.
+ */
+static int lrng_cc20_drng_generate_helper_full(void *drng, u8 *outbuf,
+					       u32 outbuflen)
+{
+	struct chacha20_state *chacha20_state = (struct chacha20_state *)drng;
+	struct chacha20_block *chacha20 = &chacha20_state->block;
+	u32 aligned_buf[CHACHA_BLOCK_WORDS];
+	u32 ret = outbuflen;
+
+	while (outbuflen >= CHACHA_BLOCK_SIZE) {
+		u32 i;
+
+		chacha20_block(&chacha20->constants[0], outbuf);
+
+		/* fold output in half */
+		for (i = 0; i < (CHACHA_BLOCK_WORDS / 2); i++)
+			outbuf[i] ^= outbuf[i + (CHACHA_BLOCK_WORDS / 2)];
+
+		outbuf += CHACHA_BLOCK_SIZE / 2;
+		outbuflen -= CHACHA_BLOCK_SIZE / 2;
+	}
+
+	while (outbuflen) {
+		u32 i, todo = min_t(u32, CHACHA_BLOCK_SIZE / 2, outbuflen);
+
+		chacha20_block(&chacha20->constants[0], (u8 *)aligned_buf);
+
+		/* fold output in half */
+		for (i = 0; i < (CHACHA_BLOCK_WORDS / 2); i++)
+			aligned_buf[i] ^=
+				aligned_buf[i + (CHACHA_BLOCK_WORDS / 2)];
+
+		memcpy(outbuf, aligned_buf, todo);
+		outbuflen -= todo;
+		outbuf += todo;
+	}
+	memzero_explicit(aligned_buf, sizeof(aligned_buf));
+
+	lrng_chacha20_update(chacha20_state, NULL, CHACHA_BLOCK_WORDS);
+
+	return ret;
+}
+
+void lrng_cc20_init_state(struct chacha20_state *state)
+{
+	struct chacha20_block *chacha20 = &state->block;
+	unsigned long v;
+	u32 i;
+
+	memcpy(&chacha20->constants[0], "expand 32-byte k", 16);
+
+	for (i = 0; i < CHACHA_KEY_SIZE_WORDS; i++) {
+		chacha20->key.u[i] ^= jiffies;
+		chacha20->key.u[i] ^= random_get_entropy();
+		if (arch_get_random_seed_long(&v) || arch_get_random_long(&v))
+			chacha20->key.u[i] ^= v;
+	}
+
+	for (i = 0; i < 3; i++) {
+		chacha20->nonce[i] ^= jiffies;
+		chacha20->nonce[i] ^= random_get_entropy();
+		if (arch_get_random_seed_long(&v) || arch_get_random_long(&v))
+			chacha20->nonce[i] ^= v;
+	}
+
+	pr_info("ChaCha20 core initialized\n");
+}
+
+/**
+ * Allocation of the DRNG state
+ */
+static void *lrng_cc20_drng_alloc(u32 sec_strength)
+{
+	struct chacha20_state *state = NULL;
+
+	if (sec_strength > CHACHA_KEY_SIZE) {
+		pr_err("Security strength of ChaCha20 DRNG (%u bits) lower "
+		       "than requested by LRNG (%u bits)\n",
+			CHACHA_KEY_SIZE * 8, sec_strength * 8);
+		return ERR_PTR(-EINVAL);
+	}
+	if (sec_strength < CHACHA_KEY_SIZE)
+		pr_warn("Security strength of ChaCha20 DRNG (%u bits) higher "
+			"than requested by LRNG (%u bits)\n",
+			CHACHA_KEY_SIZE * 8, sec_strength * 8);
+
+	state = kmalloc(sizeof(struct chacha20_state), GFP_KERNEL);
+	if (!state)
+		return ERR_PTR(-ENOMEM);
+	pr_debug("memory for ChaCha20 core allocated\n");
+
+	lrng_cc20_init_state(state);
+
+	return state;
+}
+
+static void lrng_cc20_drng_dealloc(void *drng)
+{
+	struct chacha20_state *chacha20_state = (struct chacha20_state *)drng;
+
+	if (drng == &primary_chacha20 || drng == &secondary_chacha20) {
+		memzero_explicit(chacha20_state, sizeof(*chacha20_state));
+		pr_debug("static ChaCha20 core zeroized\n");
+		return;
+	}
+
+	pr_debug("ChaCha20 core zeroized and freed\n");
+	kzfree(chacha20_state);
+}
+
+/******************************* Hash Operation *******************************/
+
+static void *lrng_cc20_hash_alloc(const u8 *key, u32 keylen)
+{
+	pr_info("Hash SHA-1 allocated\n");
+	return NULL;
+}
+
+static void lrng_cc20_hash_dealloc(void *hash)
+{
+}
+
+static u32 lrng_cc20_hash_digestsize(void *hash)
+{
+	return (SHA_DIGEST_WORDS * sizeof(u32));
+}
+
+static int lrng_cc20_hash_buffer(void *hash, const u8 *inbuf, u32 inbuflen,
+				 u8 *digest)
+{
+	u32 i;
+	u32 workspace[SHA_WORKSPACE_WORDS];
+
+	WARN_ON(inbuflen % (SHA_WORKSPACE_WORDS * sizeof(u32)));
+
+	for (i = 0; i < inbuflen; i += (SHA_WORKSPACE_WORDS * sizeof(u32)))
+		sha_transform((u32 *)digest, (inbuf + i), workspace);
+	memzero_explicit(workspace, sizeof(workspace));
+
+	return 0;
+}
+
+static const char *lrng_cc20_drng_name(void)
+{
+	const char *cc20_drng_name = "ChaCha20 DRNG";
+	return cc20_drng_name;
+}
+
+static const char *lrng_cc20_hash_name(void)
+{
+	const char *cc20_hash_name = "SHA-1";
+	return cc20_hash_name;
+}
+
+const struct lrng_crypto_cb lrng_cc20_crypto_cb = {
+	.lrng_drng_name			= lrng_cc20_drng_name,
+	.lrng_hash_name			= lrng_cc20_hash_name,
+	.lrng_drng_alloc		= lrng_cc20_drng_alloc,
+	.lrng_drng_dealloc		= lrng_cc20_drng_dealloc,
+	.lrng_drng_seed_helper		= lrng_cc20_drng_seed_helper,
+	.lrng_drng_generate_helper	= lrng_cc20_drng_generate_helper,
+	.lrng_drng_generate_helper_full	= lrng_cc20_drng_generate_helper_full,
+	.lrng_hash_alloc		= lrng_cc20_hash_alloc,
+	.lrng_hash_dealloc		= lrng_cc20_hash_dealloc,
+	.lrng_hash_digestsize		= lrng_cc20_hash_digestsize,
+	.lrng_hash_buffer		= lrng_cc20_hash_buffer,
+};
diff --git a/drivers/char/lrng/lrng_interfaces.c b/drivers/char/lrng/lrng_interfaces.c
new file mode 100644
index 000000000000..5d6af10aba81
--- /dev/null
+++ b/drivers/char/lrng/lrng_interfaces.c
@@ -0,0 +1,648 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG User and kernel space interfaces
+ *
+ * Copyright (C) 2016 - 2019, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/freezer.h>
+#include <linux/fs.h>
+#include <linux/genhd.h>
+#include <linux/kthread.h>
+#include <linux/poll.h>
+#include <linux/preempt.h>
+#include <linux/random.h>
+#include <linux/slab.h>
+#include <linux/syscalls.h>
+#include <linux/timex.h>
+
+#include "lrng_internal.h"
+
+/*
+ * The minimum number of bits of entropy before we wake up a read on
+ * /dev/random.
+ */
+u32 lrng_read_wakeup_bits = LRNG_MIN_SEED_ENTROPY_BITS +
+			    LRNG_CONDITIONING_ENTROPY_LOSS;
+
+/*
+ * If the entropy count falls under this number of bits, then we
+ * should wake up processes which are selecting or polling on write
+ * access to /dev/random.
+ */
+u32 lrng_write_wakeup_bits = LRNG_EMERG_ENTROPY +
+			     2 * LRNG_DRNG_SECURITY_STRENGTH_BITS;
+
+static LIST_HEAD(lrng_ready_list);
+static DEFINE_SPINLOCK(lrng_ready_list_lock);
+
+static DECLARE_WAIT_QUEUE_HEAD(lrng_read_wait);
+static DECLARE_WAIT_QUEUE_HEAD(lrng_write_wait);
+static DECLARE_WAIT_QUEUE_HEAD(lrng_init_wait);
+static struct fasync_struct *fasync;
+
+struct ctl_table random_table[];
+/********************************** Helper ***********************************/
+
+/* Is the primary DRNG seed level too low? */
+static inline bool lrng_need_entropy(void)
+{
+	return (lrng_avail_entropy() < lrng_write_wakeup_bits);
+}
+
+/* Is the entropy pool filled for /dev/random pull or DRNG fully seeded? */
+static inline bool lrng_have_entropy_full(void)
+{
+	return (lrng_avail_entropy() >= lrng_read_wakeup_bits);
+}
+
+void lrng_reader_wakeup(void)
+{
+	if (lrng_have_entropy_full() && wq_has_sleeper(&lrng_read_wait)) {
+		wake_up_interruptible(&lrng_read_wait);
+		kill_fasync(&fasync, SIGIO, POLL_IN);
+	}
+}
+
+void lrng_writer_wakeup(void)
+{
+	if (lrng_need_entropy() && wq_has_sleeper(&lrng_write_wait)) {
+		wake_up_interruptible(&lrng_write_wait);
+		kill_fasync(&fasync, SIGIO, POLL_OUT);
+	}
+}
+
+void lrng_init_wakeup(void)
+{
+	wake_up_all(&lrng_init_wait);
+}
+
+/**
+ * Ping all kernel internal callers waiting until the DRNG is fully
+ * seeded that the DRNG is now fully seeded.
+ *
+ * When the SP800-90B testing is enabled, the ping only happens if the SP800-90B
+ * startup health tests are completed. This implies that kernel internal
+ * callers always have an SP800-90B compliant noise source when being
+ * pinged.
+ */
+void lrng_process_ready_list(void)
+{
+	unsigned long flags;
+	struct random_ready_callback *rdy, *tmp;
+
+	if (!lrng_sp80090b_startup_complete())
+		return;
+
+	spin_lock_irqsave(&lrng_ready_list_lock, flags);
+	list_for_each_entry_safe(rdy, tmp, &lrng_ready_list, list) {
+		struct module *owner = rdy->owner;
+
+		list_del_init(&rdy->list);
+		rdy->func(rdy);
+		module_put(owner);
+	}
+	spin_unlock_irqrestore(&lrng_ready_list_lock, flags);
+}
+
+void lrng_debug_report_seedlevel(const char *name)
+{
+#ifdef CONFIG_WARN_ALL_UNSEEDED_RANDOM
+	static void *previous = NULL;
+	void *caller = (void *) _RET_IP_;
+
+	if (READ_ONCE(previous) == caller)
+		return;
+
+	if (!lrng_state_min_seeded())
+		pr_notice("%pS %s called without reaching mimimally seeded "
+			  "level (available entropy %u)\n", caller, name,
+			  lrng_avail_entropy());
+
+	WRITE_ONCE(previous, caller);
+#endif
+}
+
+/************************ LRNG kernel input interfaces ************************/
+
+/**
+ * Interface for in-kernel drivers of true hardware RNGs.
+ * Those devices may produce endless random bits and will be throttled
+ * when our pool is full.
+ *
+ * @buffer: buffer holding the entropic data from HW noise sources to be used to
+ *	    (re)seed the DRNG.
+ * @count: length of buffer
+ * @entropy_bits: amount of entropy in buffer (value is in bits)
+ */
+void add_hwgenerator_randomness(const char *buffer, size_t count,
+				size_t entropy_bits)
+{
+	/* DRNG is not yet online */
+	if (!lrng_get_available())
+		return;
+	/*
+	 * Suspend writing if we are fully loaded with entropy.
+	 * We'll be woken up again once below lrng_write_wakeup_thresh,
+	 * or when the calling thread is about to terminate.
+	 */
+	wait_event_interruptible(lrng_write_wait, lrng_need_entropy() ||
+						  kthread_should_stop() ||
+						  freezing(current));
+	lrng_pool_lfsr_nonaligned(buffer, count);
+	lrng_pool_add_entropy(entropy_bits);
+}
+EXPORT_SYMBOL_GPL(add_hwgenerator_randomness);
+
+/* Handle random seed passed by bootloader.
+ * If the seed is trustworthy, it would be regarded as hardware RNGs. Otherwise
+ * it would be regarded as device data.
+ * The decision is controlled by CONFIG_RANDOM_TRUST_BOOTLOADER.
+ */
+void add_bootloader_randomness(const void *buf, unsigned int size)
+{
+	if (IS_ENABLED(CONFIG_RANDOM_TRUST_BOOTLOADER))
+		add_hwgenerator_randomness(buf, size, size * 8);
+	else
+		add_device_randomness(buf, size);
+}
+EXPORT_SYMBOL_GPL(add_bootloader_randomness);
+
+/**
+ * Callback for HID layer -- use the HID event values to stir the entropy pool
+ */
+void add_input_randomness(unsigned int type, unsigned int code,
+			  unsigned int value)
+{
+	static unsigned char last_value;
+
+	/* ignore autorepeat and the like */
+	if (value == last_value)
+		return;
+
+	last_value = value;
+
+	lrng_pool_lfsr_u32((type << 4) ^ code ^ (code >> 4) ^ value);
+}
+EXPORT_SYMBOL_GPL(add_input_randomness);
+
+/*
+ * Add device- or boot-specific data to the input pool to help
+ * initialize it.
+ *
+ * None of this adds any entropy; it is meant to avoid the problem of
+ * the entropy pool having similar initial state across largely
+ * identical devices.
+ */
+void add_device_randomness(const void *buf, unsigned int size)
+{
+	lrng_pool_lfsr_nonaligned((u8 *)buf, size);
+	lrng_pool_lfsr_u32(random_get_entropy());
+	lrng_pool_lfsr_u32(jiffies);
+}
+EXPORT_SYMBOL(add_device_randomness);
+
+#ifdef CONFIG_BLOCK
+void rand_initialize_disk(struct gendisk *disk) { }
+void add_disk_randomness(struct gendisk *disk) { }
+EXPORT_SYMBOL(add_disk_randomness);
+#endif
+
+/**
+ * Delete a previously registered readiness callback function.
+ */
+void del_random_ready_callback(struct random_ready_callback *rdy)
+{
+	unsigned long flags;
+	struct module *owner = NULL;
+
+	spin_lock_irqsave(&lrng_ready_list_lock, flags);
+	if (!list_empty(&rdy->list)) {
+		list_del_init(&rdy->list);
+		owner = rdy->owner;
+	}
+	spin_unlock_irqrestore(&lrng_ready_list_lock, flags);
+
+	module_put(owner);
+}
+EXPORT_SYMBOL(del_random_ready_callback);
+
+/**
+ * Add a callback function that will be invoked when the DRNG is fully seeded.
+ *
+ * @return: 0 if callback is successfully added
+ *          -EALREADY if pool is already initialised (callback not called)
+ *	    -ENOENT if module for callback is not alive
+ */
+int add_random_ready_callback(struct random_ready_callback *rdy)
+{
+	struct module *owner;
+	unsigned long flags;
+	int err = -EALREADY;
+
+	if (likely(lrng_state_min_seeded()))
+		return err;
+
+	owner = rdy->owner;
+	if (!try_module_get(owner))
+		return -ENOENT;
+
+	spin_lock_irqsave(&lrng_ready_list_lock, flags);
+	if (lrng_state_min_seeded())
+		goto out;
+
+	owner = NULL;
+
+	list_add(&rdy->list, &lrng_ready_list);
+	err = 0;
+
+out:
+	spin_unlock_irqrestore(&lrng_ready_list_lock, flags);
+
+	module_put(owner);
+
+	return err;
+}
+EXPORT_SYMBOL(add_random_ready_callback);
+
+/*********************** LRNG kernel output interfaces ************************/
+
+/**
+ * Provider of cryptographic strong random numbers for kernel-internal usage.
+ * This function is appropriate for all in-kernel use cases. However,
+ * it will always use the ChaCha20 DRNG.
+ *
+ * @buf: buffer to store the random bytes
+ * @nbytes: size of the buffer
+ */
+void get_random_bytes(void *buf, int nbytes)
+{
+	lrng_sdrng_get_atomic((u8 *)buf, (u32)nbytes);
+	lrng_debug_report_seedlevel("get_random_bytes");
+}
+EXPORT_SYMBOL(get_random_bytes);
+
+/**
+ * Provider of cryptographic strong random numbers for kernel-internal usage.
+ * This function is appropriate only for non-atomic use cases as this
+ * function may sleep. Though, it provides access to the full functionality
+ * of LRNG including the switchable DRNG support, that may support other
+ * DRNGs such as the SP800-90A DRBG.
+ *
+ * @buf: buffer to store the random bytes
+ * @nbytes: size of the buffer
+ */
+void get_random_bytes_full(void *buf, int nbytes)
+{
+	lrng_sdrng_get_sleep((u8 *)buf, (u32)nbytes);
+	lrng_debug_report_seedlevel("get_random_bytes_full");
+}
+EXPORT_SYMBOL(get_random_bytes_full);
+
+/**
+ * Wait for the LRNG to be seeded and thus guaranteed to supply
+ * cryptographically secure random numbers. This applies to: the /dev/urandom
+ * device, the get_random_bytes function, and the get_random_{u32,u64,int,long}
+ * family of functions. Using any of these functions without first calling
+ * this function forfeits the guarantee of security.
+ *
+ * Returns: 0 if the LRNG has been seeded.
+ *          -ERESTARTSYS if the function was interrupted by a signal.
+ */
+int wait_for_random_bytes(void)
+{
+	if (likely(lrng_state_min_seeded()))
+		return 0;
+	return wait_event_interruptible(lrng_init_wait,
+					lrng_state_min_seeded());
+}
+EXPORT_SYMBOL(wait_for_random_bytes);
+
+/**
+ * This function will use the architecture-specific hardware random
+ * number generator if it is available.  The arch-specific hw RNG will
+ * almost certainly be faster than what we can do in software, but it
+ * is impossible to verify that it is implemented securely (as
+ * opposed, to, say, the AES encryption of a sequence number using a
+ * key known by the NSA).  So it's useful if we need the speed, but
+ * only if we're willing to trust the hardware manufacturer not to
+ * have put in a back door.
+ *
+ * @buf: buffer allocated by caller to store the random data in
+ * @nbytes: length of outbuf
+ *
+ * Return number of bytes filled in.
+ */
+int __must_check get_random_bytes_arch(void *buf, int nbytes)
+{
+	u8 *p = buf;
+
+	while (nbytes) {
+		unsigned long v;
+		int chunk = min_t(int, nbytes, sizeof(unsigned long));
+
+		if (!arch_get_random_long(&v))
+			break;
+
+		memcpy(p, &v, chunk);
+		p += chunk;
+		nbytes -= chunk;
+	}
+
+	if (nbytes)
+		lrng_sdrng_get_atomic((u8 *)p, (u32)nbytes);
+
+	return nbytes;
+}
+EXPORT_SYMBOL(get_random_bytes_arch);
+
+/************************ LRNG user output interfaces *************************/
+
+static ssize_t lrng_read_common(char __user *buf, size_t nbytes,
+			int (*lrng_read_random)(u8 *outbuf, u32 outbuflen))
+{
+	ssize_t ret = 0;
+	u8 tmpbuf[LRNG_DRNG_BLOCKSIZE] __aligned(LRNG_KCAPI_ALIGN);
+	u8 *tmp_large = NULL, *tmp = tmpbuf;
+	u32 tmplen = sizeof(tmpbuf);
+
+	if (nbytes == 0)
+		return 0;
+
+	/*
+	 * Satisfy large read requests -- as the common case are smaller
+	 * request sizes, such as 16 or 32 bytes, avoid a kmalloc overhead for
+	 * those by using the stack variable of tmpbuf.
+	 */
+	if (nbytes > sizeof(tmpbuf)) {
+		tmplen = min_t(u32, nbytes, LRNG_DRNG_MAX_REQSIZE);
+		tmp_large = kmalloc(tmplen + LRNG_KCAPI_ALIGN, GFP_KERNEL);
+		if (!tmp_large)
+			tmplen = sizeof(tmpbuf);
+		else
+			tmp = PTR_ALIGN(tmp_large, LRNG_KCAPI_ALIGN);
+	}
+
+	while (nbytes) {
+		u32 todo = min_t(u32, nbytes, tmplen);
+		int rc = 0;
+
+		/* Reschedule if we received a large request. */
+		if ((tmp_large) && need_resched()) {
+			if (signal_pending(current)) {
+				if (ret == 0)
+					ret = -ERESTARTSYS;
+				break;
+			}
+			schedule();
+		}
+
+		rc = lrng_read_random(tmp, todo);
+		if (rc <= 0) {
+			if (rc < 0)
+				ret = rc;
+			break;
+		}
+		if (copy_to_user(buf, tmp, rc)) {
+			ret = -EFAULT;
+			break;
+		}
+
+		nbytes -= rc;
+		buf += rc;
+		ret += rc;
+	}
+
+	/* Wipe data just returned from memory */
+	if (tmp_large)
+		kzfree(tmp_large);
+	else
+		memzero_explicit(tmpbuf, sizeof(tmpbuf));
+
+	return ret;
+}
+
+static ssize_t
+lrng_trng_read_common(int nonblock, char __user *buf, size_t nbytes)
+{
+	if (nbytes == 0)
+		return 0;
+
+	if (unlikely(!lrng_state_operational())) {
+		int ret;
+
+		if (nonblock)
+			return -EAGAIN;
+
+		ret = wait_event_interruptible(lrng_init_wait,
+					       lrng_state_operational());
+		if (unlikely(ret))
+			return ret;
+	}
+
+	nbytes = min_t(u32, nbytes, LRNG_DRNG_BLOCKSIZE);
+	while (1) {
+		ssize_t n = lrng_read_common(buf, nbytes, lrng_trng_get);
+
+		if (n)
+			return n;
+
+		/* No entropy available.  Maybe wait and retry. */
+		if (nonblock)
+			return -EAGAIN;
+
+		wait_event_interruptible(lrng_read_wait,
+					 lrng_have_entropy_full());
+		if (signal_pending(current))
+			return -ERESTARTSYS;
+	}
+}
+
+static ssize_t lrng_trng_read(struct file *file, char __user *buf,
+			      size_t nbytes, loff_t *ppos)
+{
+	return lrng_trng_read_common(file->f_flags & O_NONBLOCK, buf, nbytes);
+}
+
+static unsigned int lrng_trng_poll(struct file *file, poll_table *wait)
+{
+	__poll_t mask;
+
+	poll_wait(file, &lrng_read_wait, wait);
+	poll_wait(file, &lrng_write_wait, wait);
+	mask = 0;
+	if (lrng_have_entropy_full())
+		mask |= EPOLLIN | EPOLLRDNORM;
+	if (lrng_need_entropy())
+		mask |= EPOLLOUT | EPOLLWRNORM;
+	return mask;
+}
+
+static ssize_t lrng_drng_write_common(const char __user *buffer, size_t count,
+				      u32 entropy_bits)
+{
+	ssize_t ret = 0;
+	u8 buf[64] __aligned(LRNG_KCAPI_ALIGN);
+	const char __user *p = buffer;
+	u32 orig_entropy_bits = entropy_bits;
+
+	if (!lrng_get_available())
+		return -EAGAIN;
+
+	count = min_t(size_t, count, INT_MAX);
+	while (count > 0) {
+		size_t bytes = min_t(size_t, count, sizeof(buf));
+		u32 ent = min_t(u32, bytes<<3, entropy_bits);
+
+		if (copy_from_user(&buf, p, bytes))
+			return -EFAULT;
+		/* Inject data into entropy pool */
+		lrng_pool_lfsr(buf, bytes);
+		lrng_pool_add_entropy(ent);
+
+		count -= bytes;
+		p += bytes;
+		ret += bytes;
+		entropy_bits -= ent;
+
+		cond_resched();
+	}
+
+	/* Force reseed of secondary DRNG during next data request. */
+	if (!orig_entropy_bits)
+		lrng_sdrng_force_reseed();
+
+	return ret;
+}
+
+static ssize_t lrng_sdrng_read(struct file *file, char __user *buf,
+			       size_t nbytes, loff_t *ppos)
+{
+	if (!lrng_state_min_seeded())
+		pr_notice_ratelimited("%s - use of insufficiently seeded DRNG "
+				      "(%zu bytes read)\n", current->comm,
+				      nbytes);
+	else if (!lrng_state_operational())
+		pr_debug_ratelimited("%s - use of not fully seeded DRNG (%zu "
+				     "bytes read)\n", current->comm, nbytes);
+
+	return lrng_read_common(buf, nbytes, lrng_sdrng_get_sleep);
+}
+
+static ssize_t lrng_drng_write(struct file *file, const char __user *buffer,
+			       size_t count, loff_t *ppos)
+{
+	return lrng_drng_write_common(buffer, count, 0);
+}
+
+static long lrng_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
+{
+	int size, ent_count_bits;
+	int __user *p = (int __user *)arg;
+
+	switch (cmd) {
+	case RNDGETENTCNT:
+		ent_count_bits = lrng_avail_entropy();
+		if (put_user(ent_count_bits, p))
+			return -EFAULT;
+		return 0;
+	case RNDADDTOENTCNT:
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+		if (get_user(ent_count_bits, p))
+			return -EFAULT;
+		ent_count_bits = (int)lrng_avail_entropy() + ent_count_bits;
+		if (ent_count_bits < 0)
+			ent_count_bits = 0;
+		if (ent_count_bits > LRNG_POOL_SIZE_BITS)
+			ent_count_bits = LRNG_POOL_SIZE_BITS;
+		lrng_pool_set_entropy(ent_count_bits);
+		return 0;
+	case RNDADDENTROPY:
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+		if (get_user(ent_count_bits, p++))
+			return -EFAULT;
+		if (ent_count_bits < 0)
+			return -EINVAL;
+		if (get_user(size, p++))
+			return -EFAULT;
+		if (size < 0)
+			return -EINVAL;
+		/* there cannot be more entropy than data */
+		ent_count_bits = min(ent_count_bits, size<<3);
+		return lrng_drng_write_common((const char __user *)p, size,
+					      ent_count_bits);
+	case RNDZAPENTCNT:
+	case RNDCLEARPOOL:
+		/* Clear the entropy pool counter. */
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+		lrng_pool_set_entropy(0);
+		return 0;
+	case RNDRESEEDCRNG:
+		/*
+		 * We leave the capability check here since it is present
+		 * in the upstream's RNG implementation. Yet, user space
+		 * can trigger a reseed as easy as writing into /dev/random
+		 * or /dev/urandom where no privilege is needed.
+		 */
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+		/* Force a reseed of all secondary DRNGs */
+		lrng_sdrng_force_reseed();
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
+static int lrng_fasync(int fd, struct file *filp, int on)
+{
+	return fasync_helper(fd, filp, on, &fasync);
+}
+
+const struct file_operations random_fops = {
+	.read  = lrng_trng_read,
+	.write = lrng_drng_write,
+	.poll  = lrng_trng_poll,
+	.unlocked_ioctl = lrng_ioctl,
+	.fasync = lrng_fasync,
+	.llseek = noop_llseek,
+};
+
+const struct file_operations urandom_fops = {
+	.read  = lrng_sdrng_read,
+	.write = lrng_drng_write,
+	.unlocked_ioctl = lrng_ioctl,
+	.fasync = lrng_fasync,
+	.llseek = noop_llseek,
+};
+
+SYSCALL_DEFINE3(getrandom, char __user *, buf, size_t, count,
+		unsigned int, flags)
+{
+	if (flags & ~(GRND_NONBLOCK|GRND_RANDOM))
+		return -EINVAL;
+
+	if (count > INT_MAX)
+		count = INT_MAX;
+
+	if (flags & GRND_RANDOM)
+		return lrng_trng_read_common(flags & GRND_NONBLOCK, buf, count);
+
+	if (unlikely(!lrng_state_operational())) {
+		int ret;
+
+		if (flags & GRND_NONBLOCK)
+			return -EAGAIN;
+		ret = wait_event_interruptible(lrng_init_wait,
+					       lrng_state_operational());
+		if (unlikely(ret))
+			return ret;
+	}
+
+	return lrng_sdrng_read(NULL, buf, count, NULL);
+}
diff --git a/drivers/char/lrng/lrng_internal.h b/drivers/char/lrng/lrng_internal.h
new file mode 100644
index 000000000000..a3d9e0bce884
--- /dev/null
+++ b/drivers/char/lrng/lrng_internal.h
@@ -0,0 +1,300 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
+/*
+ * Copyright (C) 2018 - 2019, Stephan Mueller <smueller@chronox.de>
+ */
+
+#ifndef _LRNG_INTERNAL_H
+#define _LRNG_INTERNAL_H
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+
+/*************************** General LRNG parameter ***************************/
+
+/* Security strength of LRNG -- this must match DRNG security strength */
+#define LRNG_DRNG_SECURITY_STRENGTH_BYTES 32
+#define LRNG_DRNG_SECURITY_STRENGTH_BITS (LRNG_DRNG_SECURITY_STRENGTH_BYTES * 8)
+#define LRNG_DRNG_BLOCKSIZE 64		/* Maximum of DRNG block sizes */
+
+/*
+ * SP800-90A defines a maximum request size of 1<<16 bytes. The given value is
+ * considered a safer margin. This applies to the secondary DRNGs.
+ *
+ * This value is allowed to be changed.
+ */
+#define LRNG_DRNG_MAX_REQSIZE		(1<<12)
+
+/*
+ * SP800-90A defines a maximum number of requests between reseeds of 2^48.
+ * The given value is considered a much safer margin, balancing requests for
+ * frequent reseeds with the need to conserve entropy. This value MUST NOT be
+ * larger than INT_MAX because it is used in an atomic_t. This applies to the
+ * secondary DRNGs.
+ *
+ * This value is allowed to be changed.
+ */
+#define LRNG_DRNG_RESEED_THRESH		(1<<20)
+
+/*
+ * Number of interrupts to be recorded to assume that DRNG security strength
+ * bits of entropy are received.
+ * Note: a value below the DRNG security strength should not be defined as this
+ *	 may imply the DRNG can never be fully seeded in case other noise
+ *	 sources are unavailable.
+ *
+ * This value is allowed to be changed.
+ */
+#define LRNG_IRQ_ENTROPY_BITS		LRNG_DRNG_SECURITY_STRENGTH_BITS
+
+/*
+ * Leave given amount of entropy in bits entropy pool to serve /dev/random while
+ * /dev/urandom is stressed.
+ *
+ * This value is allowed to be changed.
+ */
+#define LRNG_EMERG_ENTROPY		(LRNG_DRNG_SECURITY_STRENGTH_BITS * 2)
+
+/*
+ * Amount of entropy that is lost with the conditioning functions of LFSR and
+ * hash_df as shown with the entropy analysis compliant to SP800-90B.
+ */
+#define LRNG_CONDITIONING_ENTROPY_LOSS	1
+
+/*
+ * Min required seed entropy is 128 bits covering the minimum entropy
+ * requirement of SP800-131A and the German BSI's TR02102.
+ *
+ * This value is allowed to be changed.
+ */
+#define LRNG_FULL_SEED_ENTROPY_BITS	LRNG_DRNG_SECURITY_STRENGTH_BITS
+#define LRNG_MIN_SEED_ENTROPY_BITS	128
+#define LRNG_INIT_ENTROPY_BITS		32
+
+/*
+ * Oversampling factor of IRQ events to obtain
+ * LRNG_DRNG_SECURITY_STRENGTH_BYTES. This factor is used when a
+ * high-resolution time stamp is not available. In this case, jiffies and
+ * register contents are used to fill the entropy pool. These noise sources
+ * are much less entropic than the high-resolution timer. The entropy content
+ * is the entropy content assumed with LRNG_IRQ_ENTROPY_BITS divided by
+ * LRNG_IRQ_OVERSAMPLING_FACTOR.
+ *
+ * This value is allowed to be changed.
+ */
+#define LRNG_IRQ_OVERSAMPLING_FACTOR	10
+
+/*
+ * Alignmask which should cover all cipher implementations
+ * WARNING: If this is changed to a value larger than 8, manual
+ * alignment is necessary as older versions of GCC may not be capable
+ * of aligning stack variables at boundaries greater than 8.
+ * In this case, PTR_ALIGN must be used.
+ */
+#define LRNG_KCAPI_ALIGN		8
+
+/************************ Default DRNG implementation *************************/
+
+extern struct chacha20_state primary_chacha20;
+extern struct chacha20_state secondary_chacha20;
+extern const struct lrng_crypto_cb lrng_cc20_crypto_cb;
+void lrng_cc20_init_state(struct chacha20_state *state);
+
+/********************************** /proc *************************************/
+
+static inline void lrng_pool_inc_numa_node(void) { }
+
+/****************************** LRNG interfaces *******************************/
+
+extern u32 lrng_read_wakeup_bits;
+extern u32 lrng_write_wakeup_bits;
+extern int lrng_sdrng_reseed_max_time;
+
+void lrng_reader_wakeup(void);
+void lrng_writer_wakeup(void);
+void lrng_init_wakeup(void);
+void lrng_debug_report_seedlevel(const char *name);
+void lrng_process_ready_list(void);
+
+/************************** Entropy pool management ***************************/
+
+#define LRNG_POOL_SIZE			(128 << CONFIG_LRNG_POOL_SIZE)
+#define LRNG_POOL_WORD_BYTES		(sizeof(atomic_t))
+#define LRNG_POOL_SIZE_BYTES		(LRNG_POOL_SIZE * LRNG_POOL_WORD_BYTES)
+#define LRNG_POOL_SIZE_BITS		(LRNG_POOL_SIZE_BYTES * 8)
+#define LRNG_POOL_WORD_BITS		(LRNG_POOL_WORD_BYTES * 8)
+
+void lrng_state_init_seed_work(void);
+u32 lrng_avail_entropy(void);
+void lrng_set_entropy_thresh(u32 new);
+int lrng_pool_trylock(void);
+void lrng_pool_unlock(void);
+void lrng_reset_state(void);
+void lrng_pool_all_numa_nodes_seeded(void);
+bool lrng_state_min_seeded(void);
+bool lrng_state_fully_seeded(void);
+bool lrng_state_operational(void);
+bool lrng_pool_highres_timer(void);
+void lrng_pool_set_entropy(u32 entropy_bits);
+void lrng_pool_configure(bool highres_timer, u32 irq_entropy_bits);
+void lrng_pool_lfsr(const u8 *buf, u32 buflen);
+void lrng_pool_lfsr_nonaligned(const u8 *buf, u32 buflen);
+void lrng_pool_lfsr_u32(u32 value);
+void lrng_pool_add_irq(u32 irq_num);
+void lrng_pool_add_entropy(u32 entropy_bits);
+
+struct entropy_buf {
+	u8 a[LRNG_DRNG_SECURITY_STRENGTH_BYTES];
+	u8 b[LRNG_DRNG_SECURITY_STRENGTH_BYTES];
+	u8 c[LRNG_DRNG_SECURITY_STRENGTH_BYTES];
+	u32 now;
+};
+
+int lrng_fill_seed_buffer(const struct lrng_crypto_cb *crypto_cb,
+			  void *hash, struct entropy_buf *entropy_buf,
+			  bool drain);
+void lrng_init_ops(u32 seed_bits);
+
+/************************** Jitter RNG Noise Source ***************************/
+
+#ifdef CONFIG_LRNG_JENT
+u32 lrng_get_jent(u8 *outbuf, unsigned int outbuflen);
+u32 lrng_jent_entropylevel(void);
+#else /* CONFIG_CRYPTO_JITTERENTROPY */
+static inline u32 lrng_get_jent(u8 *outbuf, unsigned int outbuflen) {return 0; }
+static inline u32 lrng_jent_entropylevel(void) { return 0; }
+#endif /* CONFIG_CRYPTO_JITTERENTROPY */
+
+/*************************** CPU-based Noise Source ***************************/
+
+u32 lrng_get_arch(u8 *outbuf);
+u32 lrng_slow_noise_req_entropy(u32 required_entropy_bits);
+
+/****************** True Random Number Generator processing *******************/
+
+#ifdef CONFIG_LRNG_TRNG_SUPPORT
+
+void lrng_trng_reset(void);
+void lrng_trng_init(void);
+int lrng_trng_get(u8 *outbuf, u32 outbuflen);
+int lrng_trng_seed(u8 *outbuf, u32 outbuflen, bool drain);
+# ifdef CONFIG_LRNG_DRNG_SWITCH
+int lrng_trng_switch(const struct lrng_crypto_cb *cb);
+# endif
+
+#else	/* CONFIG_LRNG_TRNG_SUPPORT */
+
+static inline void lrng_trng_reset(void) {}
+static inline void lrng_trng_init(void) {}
+#define lrng_trng_get lrng_sdrng_get_sleep
+
+# ifdef CONFIG_LRNG_DRNG_SWITCH
+static inline int lrng_trng_switch(const struct lrng_crypto_cb *cb) {return 0; }
+# endif
+
+#endif	/* CONFIG_LRNG_TRNG_SUPPORT */
+
+/************************* secondary DRNG processing **************************/
+
+/* Secondary DRNG state handle */
+struct lrng_sdrng {
+	void *sdrng;				/* DRNG handle */
+	void *hash;				/* Hash handle */
+	const struct lrng_crypto_cb *crypto_cb;	/* Crypto callbacks */
+	atomic_t requests;			/* Number of DRNG requests */
+	unsigned long last_seeded;		/* Last time it was seeded */
+	bool fully_seeded;			/* Is DRNG fully seeded? */
+	bool force_reseed;			/* Force a reseed */
+	struct mutex lock;
+	spinlock_t spin_lock;
+};
+
+extern struct mutex lrng_crypto_cb_update;
+
+struct lrng_sdrng *lrng_sdrng_init_instance(void);
+struct lrng_sdrng *lrng_sdrng_atomic_instance(void);
+
+static __always_inline bool lrng_sdrng_is_atomic(struct lrng_sdrng *sdrng)
+{
+	return (sdrng->sdrng == lrng_sdrng_atomic_instance()->sdrng);
+}
+
+/* Lock the secondary DRNG */
+static __always_inline void lrng_sdrng_lock(struct lrng_sdrng *sdrng,
+					    unsigned long *flags)
+{
+	/* Use spin lock in case the atomic DRNG context is used */
+	if (lrng_sdrng_is_atomic(sdrng))
+		spin_lock_irqsave(&sdrng->spin_lock, *flags);
+	else
+		mutex_lock(&sdrng->lock);
+}
+
+/* Unlock the secondary DRNG */
+static __always_inline void lrng_sdrng_unlock(struct lrng_sdrng *sdrng,
+					      unsigned long *flags)
+{
+	if (lrng_sdrng_is_atomic(sdrng))
+		spin_unlock_irqrestore(&sdrng->spin_lock, *flags);
+	else
+		mutex_unlock(&sdrng->lock);
+}
+
+bool lrng_get_available(void);
+void lrng_set_available(void);
+void lrng_drngs_init_cc20(void);
+void lrng_sdrng_reset(struct lrng_sdrng *sdrng);
+int lrng_sdrng_get_atomic(u8 *outbuf, u32 outbuflen);
+int lrng_sdrng_get_sleep(u8 *outbuf, u32 outbuflen);
+void lrng_sdrng_force_reseed(void);
+void lrng_sdrng_seed_work(struct work_struct *dummy);
+
+static inline struct lrng_sdrng **lrng_sdrng_instances(void) { return NULL; }
+static inline void lrng_drngs_numa_alloc(void) { return; }
+
+/************************** Health Test linking code **************************/
+
+enum lrng_health_res {
+	lrng_health_pass,		/* Health test passes on time stamp */
+	lrng_health_fail_use,		/* Time stamp unhealthy, but mix in */
+	lrng_health_fail_drop		/* Time stamp unhealthy, drop it */
+};
+
+#ifdef CONFIG_LRNG_HEALTH_TESTS
+bool lrng_sp80090b_startup_complete(void);
+bool lrng_sp80090b_compliant(void);
+
+enum lrng_health_res lrng_health_test(u32 now_time);
+void lrng_health_disable(void);
+
+void lrng_reset(void);
+#else	/* CONFIG_LRNG_HEALTH_TESTS */
+static inline bool lrng_sp80090b_startup_complete(void) { return true; }
+static inline bool lrng_sp80090b_compliant(void) { return false; }
+
+static inline enum lrng_health_res
+lrng_health_test(u32 now_time) { return lrng_health_pass; }
+static inline void lrng_health_disable(void) { }
+#endif	/* CONFIG_LRNG_HEALTH_TESTS */
+
+/****************************** Helper code ***********************************/
+
+static inline u32 atomic_read_u32(atomic_t *v)
+{
+	return (u32)atomic_read(v);
+}
+
+/*************************** Auxiliary functions ******************************/
+
+void invalidate_batched_entropy(void);
+
+/***************************** Testing code ***********************************/
+
+#ifdef CONFIG_LRNG_TESTING
+bool lrng_raw_entropy_store(u32 value);
+#else	/* CONFIG_LRNG_TESTING */
+static inline bool lrng_raw_entropy_store(u32 value) { return false; }
+#endif	/* CONFIG_LRNG_TESTING */
+
+#endif /* _LRNG_INTERNAL_H */
diff --git a/drivers/char/lrng/lrng_pool.c b/drivers/char/lrng/lrng_pool.c
new file mode 100644
index 000000000000..c2939e93f66a
--- /dev/null
+++ b/drivers/char/lrng/lrng_pool.c
@@ -0,0 +1,660 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG Entropy pool management
+ *
+ * Copyright (C) 2016 - 2019, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <asm/irq_regs.h>
+#include <linux/lrng.h>
+#include <linux/percpu.h>
+#include <linux/random.h>
+#include <linux/utsname.h>
+#include <linux/workqueue.h>
+
+#include "lrng_internal.h"
+
+struct lrng_state {
+	bool lrng_operational;			/* Is DRNG operational? */
+	bool lrng_fully_seeded;			/* Is DRNG fully seeded? */
+	bool lrng_min_seeded;			/* Is DRNG minimally seeded? */
+	struct work_struct lrng_seed_work;	/* (re)seed work queue */
+};
+
+/* Status information about IRQ noise source */
+struct lrng_irq_info {
+	atomic_t num_events;	/* Number of healthy IRQs since last read */
+	atomic_t num_events_thresh;	/* Reseed threshold */
+	atomic_t reseed_in_progress;	/* Flag for on executing reseed */
+	bool irq_highres_timer;	/* Is high-resolution timer available? */
+	u32 irq_entropy_bits;	/* LRNG_IRQ_ENTROPY_BITS? */
+};
+
+/*
+ * This is the entropy pool used by the slow noise source. Its size should
+ * be at least as large as LRNG_DRNG_SECURITY_STRENGTH_BITS.
+ *
+ * The pool array is aligned to 8 bytes to comfort the kernel crypto API cipher
+ * implementations of the hash functions used to read the pool: for some
+ * accelerated implementations, we need an alignment to avoid a realignment
+ * which involves memcpy(). The alignment to 8 bytes should satisfy all crypto
+ * implementations.
+ *
+ * LRNG_POOL_SIZE is allowed to be changed only if the taps of the polynomial
+ * used for the LFSR are changed as well. The size must be in powers of 2 due
+ * to the mask handling in lrng_pool_lfsr_u32 which uses AND instead of modulo.
+ */
+struct lrng_pool {
+	union {
+		struct {
+			/*
+			 * hash_df implementation: counter, requested_bits and
+			 * pool form a linear buffer that is used in the
+			 * hash_df function specified in SP800-90A section
+			 * 10.3.1
+			 */
+			unsigned char counter;
+			__be32 requested_bits;
+
+			/* Pool */
+			atomic_t pool[LRNG_POOL_SIZE];
+			/* Ptr into pool for next IRQ word injection */
+			atomic_t pool_ptr;
+			/* rotate for LFSR */
+			atomic_t input_rotate;
+			/* All NUMA DRNGs seeded? */
+			bool all_online_numa_node_seeded;
+			/* IRQ noise source status info */
+			struct lrng_irq_info irq_info;
+			/* Serialize read of entropy pool */
+			spinlock_t lock;
+		};
+		/*
+		 * Static SHA-1 implementation in lrng_cc20_hash_buffer
+		 * processes data 64-byte-wise. Hence, ensure proper size
+		 * of LRNG entropy pool data structure.
+		 */
+		u8 hash_input_buf[LRNG_POOL_SIZE_BYTES + 64];
+	};
+};
+
+static struct lrng_pool lrng_pool __aligned(LRNG_KCAPI_ALIGN) = {
+	.irq_info	= {
+		.irq_entropy_bits	= LRNG_IRQ_ENTROPY_BITS,
+		.num_events_thresh	= ATOMIC_INIT(LRNG_INIT_ENTROPY_BITS +
+						LRNG_CONDITIONING_ENTROPY_LOSS),
+		/* Sample IRQ pointer data at least during boot */
+		.irq_highres_timer	= false },
+	.lock		= __SPIN_LOCK_UNLOCKED(lrng_pool.lock)
+};
+
+static struct lrng_state lrng_state = { false, false, false, };
+
+/********************************** Helper ***********************************/
+
+void lrng_state_init_seed_work(void)
+{
+	INIT_WORK(&lrng_state.lrng_seed_work, lrng_sdrng_seed_work);
+}
+
+static inline u32 lrng_entropy_to_data(u32 entropy_bits)
+{
+	return ((entropy_bits * lrng_pool.irq_info.irq_entropy_bits) /
+		LRNG_DRNG_SECURITY_STRENGTH_BITS);
+}
+
+static inline u32 lrng_data_to_entropy(u32 irqnum)
+{
+	return ((irqnum * LRNG_DRNG_SECURITY_STRENGTH_BITS) /
+		lrng_pool.irq_info.irq_entropy_bits);
+}
+
+u32 lrng_avail_entropy(void)
+{
+	return min_t(u32, LRNG_POOL_SIZE_BITS, lrng_data_to_entropy(
+			atomic_read_u32(&lrng_pool.irq_info.num_events)));
+}
+
+void lrng_set_entropy_thresh(u32 new)
+{
+	atomic_set(&lrng_pool.irq_info.num_events_thresh,
+		   lrng_entropy_to_data(new));
+}
+
+/*
+ * Reading of the LRNG pool is only allowed by one caller. The reading is
+ * only performed to (re)seed the TRNG or SDRNGs. Thus, if this "lock" is
+ * already taken, the reseeding operation is in progress. The caller is not
+ * intended to wait but continue with its other operation.
+ */
+int lrng_pool_trylock(void)
+{
+	return atomic_cmpxchg(&lrng_pool.irq_info.reseed_in_progress, 0, 1);
+}
+
+void lrng_pool_unlock(void)
+{
+	atomic_set(&lrng_pool.irq_info.reseed_in_progress, 0);
+}
+
+void lrng_reset_state(void)
+{
+	struct lrng_irq_info *irq_info = &lrng_pool.irq_info;
+
+	atomic_set(&irq_info->num_events, 0);
+	lrng_state.lrng_operational = false;
+	lrng_state.lrng_fully_seeded = false;
+	lrng_state.lrng_min_seeded = false;
+	pr_debug("reset LRNG\n");
+}
+
+void lrng_pool_all_numa_nodes_seeded(void)
+{
+	lrng_pool.all_online_numa_node_seeded = true;
+}
+
+bool lrng_state_min_seeded(void)
+{
+	return lrng_state.lrng_min_seeded;
+}
+
+bool lrng_state_fully_seeded(void)
+{
+	return lrng_state.lrng_fully_seeded;
+}
+
+bool lrng_state_operational(void)
+{
+	return lrng_state.lrng_operational;
+}
+
+bool lrng_pool_highres_timer(void)
+{
+	return lrng_pool.irq_info.irq_highres_timer;
+}
+
+void lrng_pool_set_entropy(u32 entropy_bits)
+{
+	atomic_set(&lrng_pool.irq_info.num_events,
+		   lrng_entropy_to_data(entropy_bits));
+}
+
+void lrng_pool_configure(bool highres_timer, u32 irq_entropy_bits)
+{
+	struct lrng_irq_info *irq_info = &lrng_pool.irq_info;
+
+	irq_info->irq_highres_timer = highres_timer;
+	if (irq_info->irq_entropy_bits != irq_entropy_bits) {
+		irq_info->irq_entropy_bits = irq_entropy_bits;
+		/* Reset the threshold based on new oversampling factor. */
+		lrng_set_entropy_thresh(atomic_read_u32(
+						&irq_info->num_events_thresh));
+	}
+}
+
+/* invoke function with buffer aligned to 4 bytes */
+void lrng_pool_lfsr(const u8 *buf, u32 buflen)
+{
+	u32 *p_buf = (u32 *)buf;
+
+	for (; buflen >= 4; buflen -= 4)
+		lrng_pool_lfsr_u32(*p_buf++);
+
+	buf = (u8 *)p_buf;
+	while (buflen--)
+		lrng_pool_lfsr_u32(*buf++);
+}
+
+void lrng_pool_lfsr_nonaligned(const u8 *buf, u32 buflen)
+{
+	while (buflen) {
+		if (!((unsigned long)buf & (sizeof(u32) - 1))) {
+			lrng_pool_lfsr(buf, buflen);
+			return;
+		}
+
+		lrng_pool_lfsr_u32(*buf++);
+		buflen--;
+	}
+}
+
+/**************************** Interrupt processing ****************************/
+
+/*
+ * Implement a (modified) twisted Generalized Feedback Shift Register. (See M.
+ * Matsumoto & Y. Kurita, 1992.  Twisted GFSR generators. ACM Transactions on
+ * Modeling and Computer Simulation 2(3):179-194.  Also see M. Matsumoto & Y.
+ * Kurita, 1994.  Twisted GFSR generators II.  ACM Transactions on Modeling and
+ * Computer Simulation 4:254-266).
+ */
+static u32 const lrng_twist_table[8] = {
+	0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158,
+	0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 };
+
+/*
+ * The polynomials for the LFSR are taken from the document "Table of Linear
+ * Feedback Shift Registers" by Roy Ward, Tim Molteno, October 26, 2007.
+ * The first polynomial is from "Primitive Binary Polynomials" by Wayne
+ * Stahnke (1973) and is primitive as well as irreducible.
+ *
+ * Note, the tap values are smaller by one compared to the documentation because
+ * they are used as an index into an array where the index starts by zero.
+ *
+ * All polynomials were also checked to be primitive and irreducible with magma
+ * which ensures that the key property of the LFSR providing a compression
+ * function for entropy is guaranteed.
+ */
+static u32 const lrng_lfsr_polynomial[][4] = {
+	{ 127, 28, 26, 1 },			/* 128 words by Stahnke */
+	{ 255, 253, 250, 245 },			/* 256 words */
+	{ 511, 509, 506, 503 },			/* 512 words */
+	{ 1023, 1014, 1001, 1000 },		/* 1024 words */
+	{ 2047, 2034, 2033, 2028 },		/* 2048 words */
+	{ 4095, 4094, 4080, 4068 },		/* 4096 words */
+};
+
+/**
+ * Hot code path - inject data into entropy pool using LFSR
+ */
+void lrng_pool_lfsr_u32(u32 value)
+{
+	/*
+	 * Process the LFSR by altering not adjacent words but rather
+	 * more spaced apart words. Using a prime number ensures that all words
+	 * are processed evenly. As some the LFSR polynomials taps are close
+	 * together, processing adjacent words with the LSFR taps may be
+	 * inappropriate as the data just mixed-in at these taps may be not
+	 * independent from the current data to be mixed in.
+	 */
+	u32 ptr = (u32)atomic_add_return_relaxed(67, &lrng_pool.pool_ptr) &
+							(LRNG_POOL_SIZE - 1);
+	/*
+	 * Add 7 bits of rotation to the pool. At the beginning of the
+	 * pool, add an extra 7 bits rotation, so that successive passes
+	 * spread the input bits across the pool evenly.
+	 *
+	 * Note, there is a race between getting ptr and calculating
+	 * input_rotate when ptr is is obtained on two or more CPUs at the
+	 * same time. This race is irrelevant as it may only come into effect
+	 * if 3 or more CPUs race at the same time which is very unlikely. If
+	 * the race happens, it applies to one event only. As this rolling
+	 * supports the LFSR without being strictly needed, we accept this
+	 * race.
+	 */
+	u32 input_rotate = (u32)atomic_add_return_relaxed((ptr ? 7 : 14),
+					&lrng_pool.input_rotate) & 31;
+	u32 word = rol32(value, input_rotate);
+
+	BUILD_BUG_ON(LRNG_POOL_SIZE - 1 !=
+		     lrng_lfsr_polynomial[CONFIG_LRNG_POOL_SIZE][0]);
+	word ^= atomic_read_u32(&lrng_pool.pool[ptr]);
+	word ^= atomic_read_u32(&lrng_pool.pool[
+		(ptr + lrng_lfsr_polynomial[CONFIG_LRNG_POOL_SIZE][0]) &
+		       (LRNG_POOL_SIZE - 1)]);
+	word ^= atomic_read_u32(&lrng_pool.pool[
+		(ptr + lrng_lfsr_polynomial[CONFIG_LRNG_POOL_SIZE][1]) &
+		       (LRNG_POOL_SIZE - 1)]);
+	word ^= atomic_read_u32(&lrng_pool.pool[
+		(ptr + lrng_lfsr_polynomial[CONFIG_LRNG_POOL_SIZE][2]) &
+		       (LRNG_POOL_SIZE - 1)]);
+	word ^= atomic_read_u32(&lrng_pool.pool[
+		(ptr + lrng_lfsr_polynomial[CONFIG_LRNG_POOL_SIZE][3]) &
+		       (LRNG_POOL_SIZE - 1)]);
+
+	word = (word >> 3) ^ lrng_twist_table[word & 7];
+	atomic_set(&lrng_pool.pool[ptr], word);
+}
+
+/**
+ * Hot code path - mix data into entropy pool
+ */
+void lrng_pool_add_irq(u32 irq_num)
+{
+	struct lrng_irq_info *irq_info = &lrng_pool.irq_info;
+
+	atomic_add(irq_num, &irq_info->num_events);
+
+	/* Wake sleeping readers */
+	lrng_reader_wakeup();
+
+	/*
+	 * Once all secondary DRNGs are fully seeded, the interrupt noise
+	 * sources will not trigger any reseeding any more.
+	 */
+	if (likely(lrng_pool.all_online_numa_node_seeded))
+		return;
+
+	/* Only try to reseed if the DRNG is alive. */
+	if (!lrng_get_available())
+		return;
+
+	/* Only trigger the DRNG reseed if we have collected enough IRQs. */
+	if (atomic_read_u32(&lrng_pool.irq_info.num_events) <
+	    atomic_read_u32(&lrng_pool.irq_info.num_events_thresh))
+		return;
+
+	/* Ensure that the seeding only occurs once at any given time. */
+	if (lrng_pool_trylock())
+		return;
+
+	/* Seed the DRNG with IRQ noise. */
+	schedule_work(&lrng_state.lrng_seed_work);
+}
+
+void lrng_pool_add_entropy(u32 entropy_bits)
+{
+	lrng_pool_add_irq(lrng_entropy_to_data(entropy_bits));
+}
+
+/**
+ * Generate a hashed output of pool using the SP800-90A section 10.3.1 hash_df
+ * function
+ */
+static inline u32 lrng_pool_hash_df(const struct lrng_crypto_cb *crypto_cb,
+				    void *hash, u8 *outbuf, u32 requested_bits)
+{
+	struct lrng_pool *pool = &lrng_pool;
+	u32 digestsize, requested_bytes = requested_bits >> 3,
+	    generated_bytes = 0;
+	u8 digest[64] __aligned(LRNG_KCAPI_ALIGN);
+
+	digestsize = crypto_cb->lrng_hash_digestsize(hash);
+	if (digestsize > sizeof(digest)) {
+		pr_err("Digest buffer too small\n");
+		return 0;
+	}
+
+	pool->counter = 1;
+	pool->requested_bits = cpu_to_be32(requested_bytes << 3);
+
+	while (requested_bytes) {
+		u32 tocopy = min_t(u32, requested_bytes, digestsize);
+
+		/* The counter must not wrap */
+		if (pool->counter == 0)
+			goto out;
+
+		if (crypto_cb->lrng_hash_buffer(hash, (u8 *)pool,
+						LRNG_POOL_SIZE_BYTES + 64,
+						digest))
+			goto out;
+
+		/* Copy the data out to the caller */
+		memcpy(outbuf + generated_bytes, digest, tocopy);
+		requested_bytes -= tocopy;
+		generated_bytes += tocopy;
+		pool->counter++;
+	}
+
+out:
+	/* Mix read data back into pool for backtracking resistance */
+	if (generated_bytes)
+		lrng_pool_lfsr(outbuf, generated_bytes);
+	memzero_explicit(digest, digestsize);
+	return (generated_bytes<<3);
+}
+
+/**
+ * Read the entropy pool out for use.
+ *
+ * This function handles the translation from the number of received interrupts
+ * into an entropy statement. The conversion depends on LRNG_IRQ_ENTROPY_BITS
+ * which defines how many interrupts must be received to obtain 256 bits of
+ * entropy. With this value, the function lrng_data_to_entropy converts a given
+ * data size (received interrupts, requested amount of data, etc.) into an
+ * entropy statement. lrng_entropy_to_data does the reverse.
+ *
+ * Both functions are agnostic about the type of data: when the number of
+ * interrupts is processed by these functions, the resulting entropy value is in
+ * bits as we assume the entropy of interrupts is measured in bits. When data is
+ * processed, the entropy value is in bytes as the data is measured in bytes.
+ *
+ * @outbuf: buffer to store data in with size LRNG_DRNG_SECURITY_STRENGTH_BYTES
+ * @requested_entropy_bits: requested bits of entropy -- the function will
+ *			    return at least this amount of entropy if available
+ * @drain: boolean indicating that that all entropy of pool can be used
+ *	   (otherwise some emergency amount of entropy is left)
+ * @return: estimated entropy from the IRQs that was obtained
+ */
+static u32 lrng_get_pool(const struct lrng_crypto_cb *crypto_cb, void *hash,
+			 u8 *outbuf, u32 requested_entropy_bits, bool drain)
+{
+	struct lrng_pool *pool = &lrng_pool;
+	unsigned long flags;
+	u32 irq_num_events_used, irq_num_events, avail_entropy_bits;
+
+	/* This get_pool operation must only be called once at a given time! */
+	spin_lock_irqsave(&pool->lock, flags);
+
+	/* How many unused interrupts are in entropy pool? */
+	irq_num_events = atomic_read_u32(&lrng_pool.irq_info.num_events);
+	/* Convert available interrupts into entropy statement */
+	avail_entropy_bits = lrng_data_to_entropy(irq_num_events);
+
+	/* Cap available entropy to pool size */
+	avail_entropy_bits =
+			min_t(u32, avail_entropy_bits, LRNG_POOL_SIZE_BITS);
+
+	/* How much entropy we need to and can we use? */
+	if (drain) {
+		struct lrng_state *state = &lrng_state;
+
+		/* read for the TRNG or not fully seeded 2ndary DRNG */
+		if (!state->lrng_fully_seeded) {
+			/*
+			 * During boot time, we read 256 bits data with
+			 * avail_entropy_bits entropy. In case our conservative
+			 * entropy estimate underestimates the available entropy
+			 * we can transport as much available entropy as
+			 * possible. The primary DRNG is no TRNG yet.
+			 */
+			requested_entropy_bits =
+					LRNG_DRNG_SECURITY_STRENGTH_BITS;
+		} else {
+			requested_entropy_bits = min_t(u32, avail_entropy_bits,
+						       requested_entropy_bits);
+		}
+	} else {
+		/*
+		 * Read for 2ndary DRNG: leave the emergency fill level.
+		 *
+		 * Only obtain data if we have at least the requested entropy
+		 * available. The idea is to prevent the transfer of, say
+		 * one byte at a time, because one byte of entropic data
+		 * can be brute forced by an attacker.
+		 */
+		if ((requested_entropy_bits + LRNG_EMERG_ENTROPY) >
+		     avail_entropy_bits) {
+			requested_entropy_bits = 0;
+			goto out;
+		}
+	}
+
+	/* Hash is a compression function: we generate entropy amount of data */
+	requested_entropy_bits = round_down(requested_entropy_bits, 8);
+
+	requested_entropy_bits = lrng_pool_hash_df(crypto_cb, hash, outbuf,
+						   requested_entropy_bits);
+
+	/* Boot time: After getting the full buffer adjust the entropy value. */
+	requested_entropy_bits = min_t(u32, avail_entropy_bits,
+				       requested_entropy_bits);
+
+out:
+	/* Convert used entropy into interrupt number for subtraction */
+	irq_num_events_used = lrng_entropy_to_data(requested_entropy_bits);
+
+	/*
+	 * The hash_df operation entropy assessment shows that the output
+	 * entropy is one bit smaller than the input entropy. Therefore we
+	 * account for this one bit of entropy here: if we have sufficient
+	 * entropy in the LFSR, we say we used one bit of entropy more.
+	 * Otherwise we reduce the amount of entropy we say we generated with
+	 * the hash_df.
+	 */
+	if ((irq_num_events_used + LRNG_CONDITIONING_ENTROPY_LOSS) <=
+	    lrng_entropy_to_data(avail_entropy_bits)) {
+		irq_num_events_used += LRNG_CONDITIONING_ENTROPY_LOSS;
+	} else {
+		if (unlikely(requested_entropy_bits <
+			     LRNG_CONDITIONING_ENTROPY_LOSS))
+			requested_entropy_bits = 0;
+		else
+			requested_entropy_bits -=
+						LRNG_CONDITIONING_ENTROPY_LOSS;
+	}
+
+	/*
+	 * New events might have arrived in the meanwhile and we don't
+	 * want to throw them away unconditionally. On the other hand,
+	 * these new events might have been mixed in before
+	 * lrng_hash_df_pool() had been able to draw any entropy
+	 * from the pool and thus, the pool capacity might have been
+	 * exceeded at some point. Note that in theory, some events
+	 * might get lost inbetween the atomic_read() and
+	 * atomic_set() below. But that's fine, because it's no real
+	 * concern while code preventing this would come at the cost of
+	 * additional complexity. Likewise, some events which arrived
+	 * after full or partial completion of the __lrng_hash_df_pool()
+	 * above might get unnecessarily thrown away by the min()
+	 * operation below; the same argument applies there.
+	 */
+	irq_num_events = atomic_read_u32(&lrng_pool.irq_info.num_events);
+	irq_num_events = min_t(u32, irq_num_events,
+			       lrng_entropy_to_data(LRNG_POOL_SIZE_BITS));
+	irq_num_events -= irq_num_events_used;
+	atomic_set(&lrng_pool.irq_info.num_events, irq_num_events);
+
+	spin_unlock_irqrestore(&pool->lock, flags);
+
+	/* Obtain entropy statement in bits from the used entropy */
+	pr_debug("obtained %u bits of entropy from %u newly collected "
+		 "interrupts - not using %u interrupts\n",
+		 requested_entropy_bits, irq_num_events_used,
+		 irq_num_events);
+
+	return requested_entropy_bits;
+}
+
+/* Fill the seed buffer with data from the noise sources */
+int lrng_fill_seed_buffer(const struct lrng_crypto_cb *crypto_cb, void *hash,
+			  struct entropy_buf *entropy_buf, bool drain)
+{
+	struct lrng_state *state = &lrng_state;
+	u32 total_entropy_bits = 0;
+
+	/* Require at least 128 bits of entropy for any reseed. */
+	if (state->lrng_fully_seeded &&
+	    lrng_avail_entropy() <
+	    lrng_slow_noise_req_entropy(lrng_read_wakeup_bits))
+		goto wakeup;
+
+	/* Drain the pool completely during init and when /dev/random calls. */
+	total_entropy_bits = lrng_get_pool(crypto_cb, hash, entropy_buf->a,
+					   LRNG_DRNG_SECURITY_STRENGTH_BITS,
+					   drain);
+
+	/*
+	 * Concatenate the output of the noise sources. This would be the
+	 * spot to add an entropy extractor logic if desired. Note, this
+	 * has the ability to collect entropy equal or larger than the DRNG
+	 * strength to be able to feed /dev/random.
+	 */
+	total_entropy_bits += lrng_get_arch(entropy_buf->b);
+	total_entropy_bits += lrng_get_jent(entropy_buf->c,
+					    LRNG_DRNG_SECURITY_STRENGTH_BYTES);
+
+	/* also reseed the DRNG with the current time stamp */
+	entropy_buf->now = random_get_entropy();
+
+wakeup:
+	/*
+	 * Shall we wake up user space writers? This location covers
+	 * /dev/urandom as well, but also ensures that the user space provider
+	 * does not dominate the internal noise sources since in case the
+	 * first call of this function finds sufficient entropy in the TRNG, it
+	 * will not trigger the wakeup. This implies that when the next
+	 * /dev/urandom read happens, the TRNG is drained and the internal
+	 * noise sources are asked to feed the TRNG.
+	 */
+	lrng_writer_wakeup();
+
+	return total_entropy_bits;
+}
+
+/**
+ * Set the slow noise source reseed trigger threshold. The initial threshold
+ * is set to the minimum data size that can be read from the pool: a word. Upon
+ * reaching this value, the next seed threshold of 128 bits is set followed
+ * by 256 bits.
+ *
+ * @entropy_bits: size of entropy currently injected into DRNG
+ */
+void lrng_init_ops(u32 seed_bits)
+{
+	struct lrng_state *state = &lrng_state;
+
+	if (state->lrng_operational)
+		return;
+
+	/* DRNG is seeded with full security strength */
+	if (state->lrng_fully_seeded) {
+		state->lrng_operational = lrng_sp80090b_startup_complete();
+		lrng_init_wakeup();
+	} else if (seed_bits >= LRNG_FULL_SEED_ENTROPY_BITS) {
+		invalidate_batched_entropy();
+		state->lrng_fully_seeded = true;
+		state->lrng_operational = lrng_sp80090b_startup_complete();
+		state->lrng_min_seeded = true;
+		pr_info("LRNG fully seeded with %u bits of entropy\n",
+			seed_bits);
+		lrng_set_entropy_thresh(LRNG_FULL_SEED_ENTROPY_BITS +
+					LRNG_CONDITIONING_ENTROPY_LOSS);
+		lrng_process_ready_list();
+		lrng_init_wakeup();
+
+	} else if (!state->lrng_min_seeded) {
+
+		/* DRNG is seeded with at least 128 bits of entropy */
+		if (seed_bits >= LRNG_MIN_SEED_ENTROPY_BITS) {
+			invalidate_batched_entropy();
+			state->lrng_min_seeded = true;
+			pr_info("LRNG minimally seeded with %u bits of "
+				"entropy\n", seed_bits);
+			lrng_set_entropy_thresh(
+				lrng_slow_noise_req_entropy(
+					LRNG_FULL_SEED_ENTROPY_BITS +
+					LRNG_CONDITIONING_ENTROPY_LOSS));
+			lrng_process_ready_list();
+			lrng_init_wakeup();
+
+		/* DRNG is seeded with at least LRNG_INIT_ENTROPY_BITS bits */
+		} else if (seed_bits >= LRNG_INIT_ENTROPY_BITS) {
+			pr_info("LRNG initial entropy level %u bits of "
+				"entropy\n", seed_bits);
+			lrng_set_entropy_thresh(
+				lrng_slow_noise_req_entropy(
+					LRNG_MIN_SEED_ENTROPY_BITS +
+					LRNG_CONDITIONING_ENTROPY_LOSS));
+		}
+	}
+}
+
+int __init rand_initialize(void)
+{
+	ktime_t now_time = ktime_get_real();
+	unsigned int i, rand;
+
+	lrng_pool_lfsr_u32(now_time);
+	for (i = 0; i < LRNG_POOL_SIZE; i++) {
+		if (!arch_get_random_seed_int(&rand) &&
+		    !arch_get_random_int(&rand))
+			rand = random_get_entropy();
+		lrng_pool_lfsr_u32(rand);
+	}
+	lrng_pool_lfsr_nonaligned((u8 *)utsname(), sizeof(*(utsname())));
+
+	return 0;
+}
diff --git a/drivers/char/lrng/lrng_sdrng.c b/drivers/char/lrng/lrng_sdrng.c
new file mode 100644
index 000000000000..aab5ab57c61f
--- /dev/null
+++ b/drivers/char/lrng/lrng_sdrng.c
@@ -0,0 +1,436 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG secondary DRNG processing
+ *
+ * Copyright (C) 2016 - 2019, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/lrng.h>
+
+#include "lrng_internal.h"
+
+/*
+ * Maximum number of seconds between DRNG reseed intervals of the secondary
+ * DRNG. Note, this is enforced with the next request of random numbers from
+ * the secondary DRNG. Setting this value to zero implies a reseeding attempt
+ * before every generated random number.
+ */
+int lrng_sdrng_reseed_max_time = 600;
+
+static atomic_t lrng_avail = ATOMIC_INIT(0);
+
+DEFINE_MUTEX(lrng_crypto_cb_update);
+
+/* Secondary DRNG for /dev/urandom, getrandom(2), get_random_bytes */
+static struct lrng_sdrng lrng_sdrng_init = {
+	.sdrng		= &secondary_chacha20,
+	.crypto_cb	= &lrng_cc20_crypto_cb,
+	.lock		= __MUTEX_INITIALIZER(lrng_sdrng_init.lock),
+	.spin_lock	= __SPIN_LOCK_UNLOCKED(lrng_sdrng_init.spin_lock)
+};
+
+/*
+ * Secondary DRNG for get_random_bytes when called in atomic context. This
+ * DRNG will always use the ChaCha20 DRNG. It will never benefit from a
+ * DRNG switch like the "regular" secondary DRNG. If there was no DRNG
+ * switch, the atomic secondary DRNG is identical to the "regular" secondary
+ * DRNG.
+ *
+ * The reason for having this is due to the fact that DRNGs other than
+ * the ChaCha20 DRNG may sleep.
+ */
+static struct lrng_sdrng lrng_sdrng_atomic = {
+	.sdrng		= &secondary_chacha20,
+	.crypto_cb	= &lrng_cc20_crypto_cb,
+	.spin_lock	= __SPIN_LOCK_UNLOCKED(lrng_sdrng_atomic.spin_lock)
+};
+
+/********************************** Helper ************************************/
+
+bool lrng_get_available(void)
+{
+	return likely(atomic_read(&lrng_avail));
+}
+
+void lrng_set_available(void)
+{
+	atomic_set(&lrng_avail, 1);
+}
+
+struct lrng_sdrng *lrng_sdrng_init_instance(void)
+{
+	return &lrng_sdrng_init;
+}
+
+struct lrng_sdrng *lrng_sdrng_atomic_instance(void)
+{
+	return &lrng_sdrng_atomic;
+}
+
+void lrng_sdrng_reset(struct lrng_sdrng *sdrng)
+{
+	atomic_set(&sdrng->requests, LRNG_DRNG_RESEED_THRESH);
+	sdrng->last_seeded = jiffies;
+	sdrng->fully_seeded = false;
+	sdrng->force_reseed = true;
+	pr_debug("reset secondary DRNG\n");
+}
+
+/************************* Random Number Generation ***************************/
+
+/* Inject a data buffer into the secondary DRNG */
+static void lrng_sdrng_inject(struct lrng_sdrng *sdrng,
+			      const u8 *inbuf, u32 inbuflen)
+{
+	const char *drng_type = unlikely(sdrng == &lrng_sdrng_atomic) ?
+				"atomic" : "secondary";
+	unsigned long flags = 0;
+
+	BUILD_BUG_ON(LRNG_DRNG_RESEED_THRESH > INT_MAX);
+	pr_debug("seeding %s DRNG with %u bytes\n", drng_type, inbuflen);
+	lrng_sdrng_lock(sdrng, &flags);
+	if (sdrng->crypto_cb->lrng_drng_seed_helper(sdrng->sdrng,
+						    inbuf, inbuflen) < 0) {
+		pr_warn("seeding of %s DRNG failed\n", drng_type);
+		atomic_set(&sdrng->requests, 1);
+	} else {
+		pr_debug("%s DRNG stats since last seeding: %lu secs; "
+			 "generate calls: %d\n", drng_type,
+			 (time_after(jiffies, sdrng->last_seeded) ?
+			  (jiffies - sdrng->last_seeded) : 0) / HZ,
+			 (LRNG_DRNG_RESEED_THRESH -
+			  atomic_read(&sdrng->requests)));
+		sdrng->last_seeded = jiffies;
+		atomic_set(&sdrng->requests, LRNG_DRNG_RESEED_THRESH);
+		sdrng->force_reseed = false;
+
+		if (sdrng->sdrng == lrng_sdrng_atomic.sdrng) {
+			lrng_sdrng_atomic.last_seeded = jiffies;
+			atomic_set(&lrng_sdrng_atomic.requests,
+				   LRNG_DRNG_RESEED_THRESH);
+			lrng_sdrng_atomic.force_reseed = false;
+		}
+	}
+	lrng_sdrng_unlock(sdrng, &flags);
+}
+
+#ifdef CONFIG_LRNG_TRNG_SUPPORT
+static inline int _lrng_sdrng_seed(struct lrng_sdrng *sdrng)
+{
+	u8 seedbuf[LRNG_DRNG_SECURITY_STRENGTH_BYTES]
+						__aligned(LRNG_KCAPI_ALIGN);
+	int ret = lrng_trng_seed(seedbuf, sizeof(seedbuf),
+				 !sdrng->fully_seeded);
+
+	/* Update the DRNG state even though we received zero random data */
+	if (ret < 0) {
+		/* Try to reseed at next round */
+		atomic_set(&sdrng->requests, 1);
+		return ret;
+	}
+
+	lrng_sdrng_inject(sdrng, seedbuf, sizeof(seedbuf));
+	memzero_explicit(seedbuf, sizeof(seedbuf));
+
+	return ret;
+}
+#else	/* CONFIG_LRNG_TRNG_SUPPORT */
+static inline int _lrng_sdrng_seed(struct lrng_sdrng *sdrng)
+{
+	struct entropy_buf seedbuf __aligned(LRNG_KCAPI_ALIGN);
+	unsigned long flags = 0;
+	u32 total_entropy_bits;
+	int ret;
+
+	lrng_sdrng_lock(sdrng, &flags);
+	total_entropy_bits = lrng_fill_seed_buffer(sdrng->crypto_cb,
+						   sdrng->hash, &seedbuf, true);
+	lrng_sdrng_unlock(sdrng, &flags);
+
+	/* Allow the seeding operation to be called again */
+	lrng_pool_unlock();
+	lrng_init_ops(total_entropy_bits);
+	ret = total_entropy_bits >> 3;
+
+	lrng_sdrng_inject(sdrng, (u8 *)&seedbuf, sizeof(seedbuf));
+	memzero_explicit(&seedbuf, sizeof(seedbuf));
+
+	return ret;
+}
+#endif	/* CONFIG_LRNG_TRNG_SUPPORT */
+
+static int lrng_sdrng_get(struct lrng_sdrng *sdrng, u8 *outbuf, u32 outbuflen);
+static void lrng_sdrng_seed(struct lrng_sdrng *sdrng)
+{
+	int ret = _lrng_sdrng_seed(sdrng);
+
+	if (ret >= LRNG_DRNG_SECURITY_STRENGTH_BYTES)
+		sdrng->fully_seeded = true;
+
+	BUILD_BUG_ON(LRNG_MIN_SEED_ENTROPY_BITS >
+		     LRNG_DRNG_SECURITY_STRENGTH_BITS);
+
+	/*
+	 * Reseed atomic DRNG from current secondary DRNG,
+	 *
+	 * We can obtain random numbers from secondary DRNG as the lock type
+	 * chosen by lrng_sdrng_get is usable with the current caller.
+	 */
+	if ((sdrng->sdrng != lrng_sdrng_atomic.sdrng) &&
+	    (lrng_sdrng_atomic.force_reseed ||
+	     atomic_read(&lrng_sdrng_atomic.requests) <= 0 ||
+	     time_after(jiffies, lrng_sdrng_atomic.last_seeded +
+			lrng_sdrng_reseed_max_time * HZ))) {
+		u8 seedbuf[LRNG_DRNG_SECURITY_STRENGTH_BYTES]
+						__aligned(LRNG_KCAPI_ALIGN);
+
+		ret = lrng_sdrng_get(sdrng, seedbuf, sizeof(seedbuf));
+
+		if (ret < 0) {
+			pr_warn("Error generating random numbers for atomic "
+				"DRNG: %d\n", ret);
+		} else {
+			lrng_sdrng_inject(&lrng_sdrng_atomic, seedbuf, ret);
+		}
+		memzero_explicit(&seedbuf, sizeof(seedbuf));
+	}
+}
+
+static inline void _lrng_sdrng_seed_work(struct lrng_sdrng *sdrng, u32 node)
+{
+	pr_debug("reseed triggered by interrupt noise source "
+		 "for secondary DRNG on NUMA node %d\n", node);
+	lrng_sdrng_seed(sdrng);
+	if (sdrng->fully_seeded) {
+		/* Prevent reseed storm */
+		sdrng->last_seeded += node * 100 * HZ;
+		/* Prevent draining of pool on idle systems */
+		lrng_sdrng_reseed_max_time += 100;
+	}
+}
+
+/**
+ * DRNG reseed trigger: Kernel thread handler triggered by the schedule_work()
+ */
+void lrng_sdrng_seed_work(struct work_struct *dummy)
+{
+	struct lrng_sdrng **lrng_sdrng = lrng_sdrng_instances();
+	u32 node;
+
+	if (lrng_sdrng) {
+		for_each_online_node(node) {
+			struct lrng_sdrng *sdrng = lrng_sdrng[node];
+
+			if (sdrng && !sdrng->fully_seeded) {
+				_lrng_sdrng_seed_work(sdrng, node);
+				goto out;
+			}
+		}
+		lrng_pool_all_numa_nodes_seeded();
+	} else {
+		if (!lrng_sdrng_init.fully_seeded)
+			_lrng_sdrng_seed_work(&lrng_sdrng_init, 0);
+	}
+
+out:
+	/* Allow the seeding operation to be called again */
+	lrng_pool_unlock();
+}
+
+/* Force all secondary DRNGs to reseed before next generation */
+void lrng_sdrng_force_reseed(void)
+{
+	struct lrng_sdrng **lrng_sdrng = lrng_sdrng_instances();
+	u32 node;
+
+	if (!lrng_sdrng) {
+		lrng_sdrng_init.force_reseed = true;
+		pr_debug("force reseed of initial secondary DRNG\n");
+		return;
+	}
+	for_each_online_node(node) {
+		struct lrng_sdrng *sdrng = lrng_sdrng[node];
+
+		if (!sdrng)
+			continue;
+
+		sdrng->force_reseed = true;
+		pr_debug("force reseed of secondary DRNG on node %u\n", node);
+	}
+	lrng_sdrng_atomic.force_reseed = true;
+}
+
+/**
+ * Get random data out of the secondary DRNG which is reseeded frequently.
+ *
+ * @outbuf: buffer for storing random data
+ * @outbuflen: length of outbuf
+ * @return: < 0 in error case (DRNG generation or update failed)
+ *	    >=0 returning the returned number of bytes
+ */
+static int lrng_sdrng_get(struct lrng_sdrng *sdrng, u8 *outbuf, u32 outbuflen)
+{
+	unsigned long flags = 0;
+	u32 processed = 0;
+
+	if (!outbuf || !outbuflen)
+		return 0;
+
+	outbuflen = min_t(size_t, outbuflen, INT_MAX);
+
+	lrng_drngs_init_cc20();
+
+	while (outbuflen) {
+		u32 todo = min_t(u32, outbuflen, LRNG_DRNG_MAX_REQSIZE);
+		int ret;
+
+		/* All but the atomic DRNG are seeded during generation */
+		if (atomic_dec_and_test(&sdrng->requests) ||
+		    sdrng->force_reseed ||
+		    time_after(jiffies, sdrng->last_seeded +
+			       lrng_sdrng_reseed_max_time * HZ)) {
+			if (likely(sdrng != &lrng_sdrng_atomic)) {
+				if (lrng_pool_trylock())
+					atomic_set(&sdrng->requests, 1);
+				else
+					lrng_sdrng_seed(sdrng);
+			}
+		}
+
+		lrng_sdrng_lock(sdrng, &flags);
+		ret = sdrng->crypto_cb->lrng_drng_generate_helper(
+					sdrng->sdrng, outbuf + processed, todo);
+		lrng_sdrng_unlock(sdrng, &flags);
+		if (ret <= 0) {
+			pr_warn("getting random data from secondary DRNG "
+				"failed (%d)\n", ret);
+			return -EFAULT;
+		}
+		processed += ret;
+		outbuflen -= ret;
+	}
+
+	return processed;
+}
+
+int lrng_sdrng_get_atomic(u8 *outbuf, u32 outbuflen)
+{
+	return lrng_sdrng_get(&lrng_sdrng_atomic, outbuf, outbuflen);
+}
+
+int lrng_sdrng_get_sleep(u8 *outbuf, u32 outbuflen)
+{
+	struct lrng_sdrng **lrng_sdrng = lrng_sdrng_instances();
+	struct lrng_sdrng *sdrng = &lrng_sdrng_init;
+	int node = numa_node_id();
+
+	might_sleep();
+
+	if (lrng_sdrng && lrng_sdrng[node] && lrng_sdrng[node]->fully_seeded)
+		sdrng = lrng_sdrng[node];
+
+	return lrng_sdrng_get(sdrng, outbuf, outbuflen);
+}
+
+/* Initialize the default DRNG during boot */
+void lrng_drngs_init_cc20(void)
+{
+	unsigned long flags = 0;
+
+	if (lrng_get_available())
+		return;
+
+	lrng_sdrng_lock(&lrng_sdrng_init, &flags);
+	if (lrng_get_available()) {
+		lrng_sdrng_unlock(&lrng_sdrng_init, &flags);
+		return;
+	}
+
+	if (random_get_entropy() || random_get_entropy()) {
+		/*
+		 * As the highres timer is identified here, previous interrupts
+		 * obtained during boot time are treated like a lowres-timer
+		 * would have been present.
+		 */
+		lrng_pool_configure(true, LRNG_IRQ_ENTROPY_BITS);
+	} else {
+		lrng_health_disable();
+		lrng_pool_configure(false, LRNG_IRQ_ENTROPY_BITS *
+					   LRNG_IRQ_OVERSAMPLING_FACTOR);
+		pr_warn("operating without high-resolution timer and applying "
+			"IRQ oversampling factor %u\n",
+			LRNG_IRQ_OVERSAMPLING_FACTOR);
+	}
+
+	lrng_sdrng_reset(&lrng_sdrng_init);
+	lrng_cc20_init_state(&secondary_chacha20);
+	lrng_state_init_seed_work();
+	lrng_sdrng_unlock(&lrng_sdrng_init, &flags);
+
+	lrng_sdrng_lock(&lrng_sdrng_atomic, &flags);
+	lrng_sdrng_reset(&lrng_sdrng_atomic);
+	/*
+	 * We do not initialize the state of the atomic DRNG as it is identical
+	 * to the secondary DRNG at this point.
+	 */
+	lrng_sdrng_unlock(&lrng_sdrng_atomic, &flags);
+
+	lrng_trng_init();
+
+	lrng_set_available();
+}
+
+/* Reset LRNG such that all existing entropy is gone */
+static void _lrng_reset(struct work_struct *work)
+{
+	struct lrng_sdrng **lrng_sdrng = lrng_sdrng_instances();
+	unsigned long flags = 0;
+
+	lrng_reset_state();
+	lrng_trng_reset();
+
+	if (!lrng_sdrng) {
+		lrng_sdrng_lock(&lrng_sdrng_init, &flags);
+		lrng_sdrng_reset(&lrng_sdrng_init);
+		lrng_sdrng_unlock(&lrng_sdrng_init, &flags);
+	} else {
+		u32 node;
+
+		for_each_online_node(node) {
+			struct lrng_sdrng *sdrng = lrng_sdrng[node];
+
+			if (!sdrng)
+				continue;
+			lrng_sdrng_lock(sdrng, &flags);
+			lrng_sdrng_reset(sdrng);
+			lrng_sdrng_unlock(sdrng, &flags);
+		}
+	}
+	lrng_set_entropy_thresh(LRNG_INIT_ENTROPY_BITS +
+				LRNG_CONDITIONING_ENTROPY_LOSS);
+}
+
+static DECLARE_WORK(lrng_reset_work, _lrng_reset);
+
+void lrng_reset(void)
+{
+	schedule_work(&lrng_reset_work);
+}
+
+/***************************** Initialize LRNG *******************************/
+
+static int __init lrng_init(void)
+{
+	lrng_drngs_init_cc20();
+
+	lrng_drngs_numa_alloc();
+	return 0;
+}
+
+late_initcall(lrng_init);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
+MODULE_DESCRIPTION("Linux Random Number Generator");
diff --git a/drivers/char/lrng/lrng_sw_noise.c b/drivers/char/lrng/lrng_sw_noise.c
new file mode 100644
index 000000000000..36b6382ffe6d
--- /dev/null
+++ b/drivers/char/lrng/lrng_sw_noise.c
@@ -0,0 +1,144 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG Slow Noise Source: Interrupt data collection
+ *
+ * Copyright (C) 2016 - 2019, Stephan Mueller <smueller@chronox.de>
+ */
+
+#include <asm/irq_regs.h>
+#include <asm/ptrace.h>
+#include <linux/random.h>
+
+#include "lrng_internal.h"
+
+/*
+ * To limit the impact on the interrupt handling, the LRNG concatenates
+ * entropic LSB parts of the time stamps in a per-CPU array and only
+ * injects them into the entropy pool when the array is full.
+ */
+/* Number of time values to store in the array */
+#define LRNG_TIME_NUM_VALUES		(64)
+/* Mask of LSB of time stamp to store */
+#define LRNG_TIME_WORD_MASK		(LRNG_TIME_NUM_VALUES - 1)
+
+/* Store multiple integers in one u32 */
+#define LRNG_TIME_SLOTSIZE_BITS		(8)
+#define LRNG_TIME_SLOTSIZE_MASK		((1 << LRNG_TIME_SLOTSIZE_BITS) - 1)
+#define LRNG_TIME_ARRAY_MEMBER_BITS	(sizeof(u32) << 3)
+#define LRNG_TIME_SLOTS_PER_UINT	(LRNG_TIME_ARRAY_MEMBER_BITS / \
+					 LRNG_TIME_SLOTSIZE_BITS)
+#define LRNG_TIME_SLOTS_MASK		(LRNG_TIME_SLOTS_PER_UINT - 1)
+#define LRNG_TIME_ARRAY_SIZE		(LRNG_TIME_NUM_VALUES /	\
+					 LRNG_TIME_SLOTS_PER_UINT)
+
+/* Holder of time stamps before mixing them into the entropy pool */
+static DEFINE_PER_CPU(u32 [LRNG_TIME_ARRAY_SIZE], lrng_time);
+static DEFINE_PER_CPU(u32, lrng_time_ptr) = 0;
+static DEFINE_PER_CPU(u8, lrng_time_irqs) = 0;
+
+/* Starting bit index of slot */
+static inline unsigned int lrng_time_slot2bitindex(unsigned int slot)
+{
+	return (LRNG_TIME_SLOTSIZE_BITS * slot);
+}
+
+/* Convert index into the array index */
+static inline unsigned int lrng_time_idx2array(unsigned int idx)
+{
+	return idx / LRNG_TIME_SLOTS_PER_UINT;
+}
+
+/* Convert index into the slot of a given array index */
+static inline unsigned int lrng_time_idx2slot(unsigned int idx)
+{
+	return idx & LRNG_TIME_SLOTS_MASK;
+}
+
+/* Convert value into slot value */
+static inline unsigned int lrng_time_slot_val(unsigned int val,
+					      unsigned int slot)
+{
+	return val << lrng_time_slot2bitindex(slot);
+}
+
+/**
+ * Batching up of entropy in per-CPU array before injecting into entropy pool.
+ */
+static inline void lrng_time_process(void)
+{
+	u32 i, ptr, now_time = random_get_entropy() &
+			       (likely(lrng_state_fully_seeded()) ?
+				LRNG_TIME_SLOTSIZE_MASK : (u32)-1);
+	enum lrng_health_res health_test;
+
+	/* Ensure sufficient space in lrng_time_irqs */
+	BUILD_BUG_ON(LRNG_TIME_NUM_VALUES >= (1 << (sizeof(u8) << 3)));
+	BUILD_BUG_ON(LRNG_TIME_ARRAY_MEMBER_BITS % LRNG_TIME_SLOTSIZE_BITS);
+
+	if (lrng_raw_entropy_store(now_time))
+		return;
+
+	health_test = lrng_health_test(now_time);
+	if (health_test > lrng_health_fail_use)
+		return;
+
+	/* During boot time, we mix the full time stamp directly into LFSR */
+	if (unlikely(!lrng_state_fully_seeded())) {
+		lrng_pool_lfsr_u32(now_time);
+		if (health_test == lrng_health_pass)
+			lrng_pool_add_irq(1);
+		return;
+	}
+
+	ptr = this_cpu_inc_return(lrng_time_ptr) & LRNG_TIME_WORD_MASK;
+	this_cpu_or(lrng_time[lrng_time_idx2array(ptr)],
+		    lrng_time_slot_val(now_time & LRNG_TIME_SLOTSIZE_MASK,
+				       lrng_time_idx2slot(ptr)));
+
+	/* Interrupt delivers entropy if health test passes */
+	if (health_test == lrng_health_pass)
+		this_cpu_inc(lrng_time_irqs);
+
+	/* Only mix the buffer of time stamps into LFSR when wrapping */
+	if (ptr < LRNG_TIME_WORD_MASK)
+		return;
+
+	for (i = 0; i < LRNG_TIME_ARRAY_SIZE; i++) {
+		lrng_pool_lfsr_u32(this_cpu_read(lrng_time[i]));
+		this_cpu_write(lrng_time[i], 0);
+	}
+	lrng_pool_add_irq(this_cpu_read(lrng_time_irqs));
+	this_cpu_write(lrng_time_irqs, 0);
+}
+
+/**
+ * Hot code path - Callback for interrupt handler
+ */
+void add_interrupt_randomness(int irq, int irq_flags)
+{
+	lrng_time_process();
+
+	if (!lrng_pool_highres_timer()) {
+		struct pt_regs *regs = get_irq_regs();
+		static atomic_t reg_idx = ATOMIC_INIT(0);
+		u64 ip;
+
+		lrng_pool_lfsr_u32(jiffies);
+		lrng_pool_lfsr_u32(irq);
+		lrng_pool_lfsr_u32(irq_flags);
+
+		if (regs) {
+			u32 *ptr = (u32 *)regs;
+			int reg_ptr = atomic_add_return_relaxed(1, &reg_idx);
+			size_t n = (sizeof(struct pt_regs) / sizeof(u32));
+
+			ip = instruction_pointer(regs);
+			lrng_pool_lfsr_u32(*(ptr + (reg_ptr % n)));
+		} else
+			ip = _RET_IP_;
+
+		lrng_pool_lfsr_u32(ip >> 32);
+		lrng_pool_lfsr_u32(ip);
+	}
+}
+EXPORT_SYMBOL(add_interrupt_randomness);
diff --git a/include/linux/lrng.h b/include/linux/lrng.h
new file mode 100644
index 000000000000..2ece3a66e0f5
--- /dev/null
+++ b/include/linux/lrng.h
@@ -0,0 +1,83 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
+/*
+ * Copyright (C) 2018 - 2019, Stephan Mueller <smueller@chronox.de>
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#ifndef _LRNG_H
+#define _LRNG_H
+
+#include <linux/types.h>
+
+/**
+ * struct lrng_crypto_cb - cryptographic callback functions
+ * @lrng_drng_name		Name of DRNG
+ * @lrng_hash_name		Name of Hash used for reading entropy pool
+ * @lrng_drng_alloc:		Allocate DRNG -- the provided integer should be
+ *				used for sanity checks.
+ *				return: allocated data structure or PTR_ERR on
+ *					error
+ * @lrng_drng_dealloc:		Deallocate DRNG
+ * @lrng_drng_seed_helper:	Seed the DRNG with data of arbitrary length
+ *				drng: is pointer to data structure allocated
+ *				      with lrng_drng_alloc
+ *				return: >= 0 on success, < 0 on error
+ * @lrng_drng_generate_helper:	Generate random numbers from the DRNG with
+ *				arbitrary length
+ * @lrng_drng_generate_helper_full: Generate random numbers from the DRNG with
+ *				    arbitrary length where the output is
+ *				    capable of providing 1 bit of entropy per
+ *				    data bit.
+ *				    return: generated number of bytes,
+ *					    < 0 on error
+ * @lrng_hash_alloc:		Allocate the hash for reading the entropy pool
+ *				return: allocated data structure (NULL is
+ *					success too) or ERR_PTR on error
+ * @lrng_hash_dealloc:		Deallocate Hash
+ * @lrng_hash_digestsize:	Return the digestsize for the used hash to read
+ *				out entropy pool
+ *				hash: is pointer to data structure allocated
+ *				      with lrng_hash_alloc
+ *				return: size of digest of hash in bytes
+ * @lrng_hash_buffer:		Generate hash
+ *				hash: is pointer to data structure allocated
+ *				      with lrng_hash_alloc
+ *				return: 0 on success, < 0 on error
+ */
+struct lrng_crypto_cb {
+	const char *(*lrng_drng_name)(void);
+	const char *(*lrng_hash_name)(void);
+	void *(*lrng_drng_alloc)(u32 sec_strength);
+	void (*lrng_drng_dealloc)(void *drng);
+	int (*lrng_drng_seed_helper)(void *drng, const u8 *inbuf, u32 inbuflen);
+	int (*lrng_drng_generate_helper)(void *drng, u8 *outbuf, u32 outbuflen);
+	int (*lrng_drng_generate_helper_full)(void *drng, u8 *outbuf,
+					      u32 outbuflen);
+	void *(*lrng_hash_alloc)(const u8 *key, u32 keylen);
+	void (*lrng_hash_dealloc)(void *hash);
+	u32 (*lrng_hash_digestsize)(void *hash);
+	int (*lrng_hash_buffer)(void *hash, const u8 *inbuf, u32 inbuflen,
+				u8 *digest);
+};
+
+/* Register cryptographic backend */
+#ifdef CONFIG_LRNG_DRNG_SWITCH
+int lrng_set_drng_cb(const struct lrng_crypto_cb *cb);
+#else	/* CONFIG_LRNG_DRNG_SWITCH */
+static inline int
+lrng_set_drng_cb(const struct lrng_crypto_cb *cb) { return -EOPNOTSUPP; }
+#endif	/* CONFIG_LRNG_DRNG_SWITCH */
+
+#endif /* _LRNG_H */
-- 
2.23.0





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v25 02/12] LRNG - allocate one SDRNG instance per NUMA node
  2019-11-16  9:32 ` [PATCH v25 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
  2019-11-16  9:33   ` [PATCH v25 01/12] Linux Random Number Generator Stephan Müller
@ 2019-11-16  9:33   ` Stephan Müller
  2019-11-16  9:34   ` [PATCH v25 03/12] LRNG - /proc interface Stephan Müller
                     ` (10 subsequent siblings)
  12 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-16  9:33 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

In order to improve NUMA-locality when serving getrandom(2) requests,
allocate one DRNG instance per node.

The SDRNG instance that is present right from the start of the kernel is
reused as the first per-NUMA-node SDRNG. For all remaining online NUMA
nodes a new SDRNG instance is allocated.

During boot time, the multiple SDRNG instances are seeded sequentially.
With this, the first SDRNG instance (referenced as the initial SDRNG
in the code) is completely seeded with 256 bits of entropy before the
next SDRNG instance is completely seeded.

When random numbers are requested, the NUMA-node-local SDRNG is checked
whether it has been already fully seeded. If this is not the case, the
initial SDRNG is used to serve the request.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Makefile        |   2 +
 drivers/char/lrng/lrng_internal.h |   5 ++
 drivers/char/lrng/lrng_numa.c     | 101 ++++++++++++++++++++++++++++++
 3 files changed, 108 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_numa.c

diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index 2761623715d2..a00cddb45773 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -7,3 +7,5 @@ obj-y				+= lrng_pool.o lrng_aux.o \
 				   lrng_sw_noise.o lrng_archrandom.o \
 				   lrng_sdrng.o lrng_chacha20.o \
 				   lrng_interfaces.o \
+
+obj-$(CONFIG_NUMA)		+= lrng_numa.o
diff --git a/drivers/char/lrng/lrng_internal.h b/drivers/char/lrng/lrng_internal.h
index a3d9e0bce884..e1f9b6b166fd 100644
--- a/drivers/char/lrng/lrng_internal.h
+++ b/drivers/char/lrng/lrng_internal.h
@@ -250,8 +250,13 @@ int lrng_sdrng_get_sleep(u8 *outbuf, u32 outbuflen);
 void lrng_sdrng_force_reseed(void);
 void lrng_sdrng_seed_work(struct work_struct *dummy);
 
+#ifdef CONFIG_NUMA
+struct lrng_sdrng **lrng_sdrng_instances(void);
+void lrng_drngs_numa_alloc(void);
+#else	/* CONFIG_NUMA */
 static inline struct lrng_sdrng **lrng_sdrng_instances(void) { return NULL; }
 static inline void lrng_drngs_numa_alloc(void) { return; }
+#endif /* CONFIG_NUMA */
 
 /************************** Health Test linking code **************************/
 
diff --git a/drivers/char/lrng/lrng_numa.c b/drivers/char/lrng/lrng_numa.c
new file mode 100644
index 000000000000..5401f927919a
--- /dev/null
+++ b/drivers/char/lrng/lrng_numa.c
@@ -0,0 +1,101 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG NUMA support
+ *
+ * Copyright (C) 2016 - 2019, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/lrng.h>
+#include <linux/slab.h>
+
+#include "lrng_internal.h"
+
+static struct lrng_sdrng **lrng_sdrng __read_mostly = NULL;
+
+struct lrng_sdrng **lrng_sdrng_instances(void)
+{
+	return lrng_sdrng;
+}
+
+/* Allocate the data structures for the per-NUMA node DRNGs */
+static void _lrng_drngs_numa_alloc(struct work_struct *work)
+{
+	struct lrng_sdrng **sdrngs;
+	struct lrng_sdrng *lrng_sdrng_init = lrng_sdrng_init_instance();
+	u32 node;
+	bool init_sdrng_used = false;
+
+	mutex_lock(&lrng_crypto_cb_update);
+
+	/* per-NUMA-node DRNGs are already present */
+	if (lrng_sdrng)
+		goto unlock;
+
+	sdrngs = kcalloc(nr_node_ids, sizeof(void *), GFP_KERNEL|__GFP_NOFAIL);
+	for_each_online_node(node) {
+		struct lrng_sdrng *sdrng;
+
+		if (!init_sdrng_used) {
+			sdrngs[node] = lrng_sdrng_init;
+			init_sdrng_used = true;
+			continue;
+		}
+
+		sdrng = kmalloc_node(sizeof(struct lrng_sdrng),
+				     GFP_KERNEL|__GFP_NOFAIL, node);
+		memset(sdrng, 0, sizeof(lrng_sdrng));
+
+		sdrng->crypto_cb = lrng_sdrng_init->crypto_cb;
+		sdrng->sdrng = sdrng->crypto_cb->lrng_drng_alloc(
+					LRNG_DRNG_SECURITY_STRENGTH_BYTES);
+		if (IS_ERR(sdrng->sdrng)) {
+			kfree(sdrng);
+			goto err;
+		}
+
+		mutex_init(&sdrng->lock);
+		spin_lock_init(&sdrng->spin_lock);
+
+		/*
+		 * No reseeding of NUMA DRNGs from previous DRNGs as this
+		 * would complicate the code. Let it simply reseed.
+		 */
+		lrng_sdrng_reset(sdrng);
+		sdrngs[node] = sdrng;
+
+		lrng_pool_inc_numa_node();
+		pr_info("secondary DRNG for NUMA node %d allocated\n", node);
+	}
+
+	/* Ensure that all NUMA nodes receive changed memory here. */
+	mb();
+
+	if (!cmpxchg(&lrng_sdrng, NULL, sdrngs))
+		goto unlock;
+
+err:
+	for_each_online_node(node) {
+		struct lrng_sdrng *sdrng = sdrngs[node];
+
+		if (sdrng == lrng_sdrng_init)
+			continue;
+
+		if (sdrng) {
+			sdrng->crypto_cb->lrng_drng_dealloc(sdrng->sdrng);
+			kfree(sdrng);
+		}
+	}
+	kfree(sdrngs);
+
+unlock:
+	mutex_unlock(&lrng_crypto_cb_update);
+}
+
+static DECLARE_WORK(lrng_drngs_numa_alloc_work, _lrng_drngs_numa_alloc);
+
+void lrng_drngs_numa_alloc(void)
+{
+	schedule_work(&lrng_drngs_numa_alloc_work);
+}
-- 
2.23.0





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v25 03/12] LRNG - /proc interface
  2019-11-16  9:32 ` [PATCH v25 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
  2019-11-16  9:33   ` [PATCH v25 01/12] Linux Random Number Generator Stephan Müller
  2019-11-16  9:33   ` [PATCH v25 02/12] LRNG - allocate one SDRNG instance per NUMA node Stephan Müller
@ 2019-11-16  9:34   ` Stephan Müller
  2019-11-16 16:39     ` Andy Lutomirski
  2019-11-16 23:36     ` Eric W. Biederman
  2019-11-16  9:34   ` [PATCH v25 04/12] LRNG - add switchable DRNG support Stephan Müller
                     ` (9 subsequent siblings)
  12 siblings, 2 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-16  9:34 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

The LRNG /proc interface provides the same files as the legacy
/dev/random. These files behave identically. Yet, all files are
documented at [1].

In addition, it provides the file lrng_type which provides details about
the LRNG:

- is the TRNG present

- the name of the DRNG that produces the random numbers for /dev/random,
/dev/urandom, getrandom(2)

- the hash used to produce random numbers from the entropy pool

- the number of secondary DRNG instances

- indicator whether the LRNG operates SP800-90B compliant

- indicator whether a high-resolution timer is identified - only with a
high-resolution timer the interrupt noise source will deliver sufficient
entropy

- indicator whether the LRNG has been minimally seeded (i.e. is the
secondary DRNG seeded with at least 128 bits of of entropy)

- indicator whether the LRNG has been fully seeded (i.e. is the
secondary DRNG seeded with at least 256 bits of entropy)

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

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Makefile          |   1 +
 drivers/char/lrng/lrng_interfaces.c |   1 -
 drivers/char/lrng/lrng_internal.h   |   4 +
 drivers/char/lrng/lrng_proc.c       | 179 ++++++++++++++++++++++++++++
 4 files changed, 184 insertions(+), 1 deletion(-)
 create mode 100644 drivers/char/lrng/lrng_proc.c

diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index a00cddb45773..b6240b73e33d 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -9,3 +9,4 @@ obj-y				+= lrng_pool.o lrng_aux.o \
 				   lrng_interfaces.o \
 
 obj-$(CONFIG_NUMA)		+= lrng_numa.o
+obj-$(CONFIG_SYSCTL)		+= lrng_proc.o
diff --git a/drivers/char/lrng/lrng_interfaces.c b/drivers/char/lrng/lrng_interfaces.c
index 5d6af10aba81..c90b24239565 100644
--- a/drivers/char/lrng/lrng_interfaces.c
+++ b/drivers/char/lrng/lrng_interfaces.c
@@ -43,7 +43,6 @@ static DECLARE_WAIT_QUEUE_HEAD(lrng_write_wait);
 static DECLARE_WAIT_QUEUE_HEAD(lrng_init_wait);
 static struct fasync_struct *fasync;
 
-struct ctl_table random_table[];
 /********************************** Helper ***********************************/
 
 /* Is the primary DRNG seed level too low? */
diff --git a/drivers/char/lrng/lrng_internal.h b/drivers/char/lrng/lrng_internal.h
index e1f9b6b166fd..9ace72f9cc21 100644
--- a/drivers/char/lrng/lrng_internal.h
+++ b/drivers/char/lrng/lrng_internal.h
@@ -103,7 +103,11 @@ void lrng_cc20_init_state(struct chacha20_state *state);
 
 /********************************** /proc *************************************/
 
+#ifdef CONFIG_SYSCTL
+void lrng_pool_inc_numa_node(void);
+#else
 static inline void lrng_pool_inc_numa_node(void) { }
+#endif
 
 /****************************** LRNG interfaces *******************************/
 
diff --git a/drivers/char/lrng/lrng_proc.c b/drivers/char/lrng/lrng_proc.c
new file mode 100644
index 000000000000..bb1863cbf96b
--- /dev/null
+++ b/drivers/char/lrng/lrng_proc.c
@@ -0,0 +1,179 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG proc interfaces
+ *
+ * Copyright (C) 2016 - 2019, Stephan Mueller <smueller@chronox.de>
+ */
+
+#include <linux/lrng.h>
+#include <linux/sysctl.h>
+#include <linux/uuid.h>
+
+#include "lrng_internal.h"
+
+/* Number of online DRNGs */
+static u32 numa_drngs = 1;
+
+void lrng_pool_inc_numa_node(void)
+{
+	numa_drngs++;
+}
+
+/*
+ * This function is used to return both the bootid UUID, and random
+ * UUID.  The difference is in whether table->data is NULL; if it is,
+ * then a new UUID is generated and returned to the user.
+ *
+ * If the user accesses this via the proc interface, the UUID will be
+ * returned as an ASCII string in the standard UUID format; if via the
+ * sysctl system call, as 16 bytes of binary data.
+ */
+static int lrng_proc_do_uuid(struct ctl_table *table, int write,
+			     void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	struct ctl_table fake_table;
+	unsigned char buf[64], tmp_uuid[16], *uuid;
+
+	uuid = table->data;
+	if (!uuid) {
+		uuid = tmp_uuid;
+		generate_random_uuid(uuid);
+	} else {
+		static DEFINE_SPINLOCK(bootid_spinlock);
+
+		spin_lock(&bootid_spinlock);
+		if (!uuid[8])
+			generate_random_uuid(uuid);
+		spin_unlock(&bootid_spinlock);
+	}
+
+	sprintf(buf, "%pU", uuid);
+
+	fake_table.data = buf;
+	fake_table.maxlen = sizeof(buf);
+
+	return proc_dostring(&fake_table, write, buffer, lenp, ppos);
+}
+
+static int lrng_proc_do_type(struct ctl_table *table, int write,
+			     void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	struct lrng_sdrng *lrng_sdrng_init = lrng_sdrng_init_instance();
+	struct ctl_table fake_table;
+	unsigned long flags = 0;
+	unsigned char buf[300];
+
+	lrng_sdrng_lock(lrng_sdrng_init, &flags);
+	snprintf(buf, sizeof(buf),
+#ifdef CONFIG_LRNG_TRNG_SUPPORT
+		 "TRNG present: true\n"
+#else
+		 "TRNG present: false\n"
+#endif
+		 "DRNG name: %s\n"
+		 "Hash for reading entropy pool: %s\n"
+		 "DRNG security strength: %d bits\n"
+		 "number of secondary DRNG instances: %u\n"
+		 "SP800-90B compliance: %s\n"
+		 "High-resolution timer: %s\n"
+		 "LRNG minimally seeded: %s\n"
+		 "LRNG fully seeded: %s",
+		 lrng_sdrng_init->crypto_cb->lrng_drng_name(),
+		 lrng_sdrng_init->crypto_cb->lrng_hash_name(),
+		 LRNG_DRNG_SECURITY_STRENGTH_BITS, numa_drngs,
+		 lrng_sp80090b_compliant() ? "true" : "false",
+		 lrng_pool_highres_timer() ? "true" : "false",
+		 lrng_state_min_seeded() ? "true" : "false",
+		 lrng_state_fully_seeded() ? "true" : "false");
+	lrng_sdrng_unlock(lrng_sdrng_init, &flags);
+
+	fake_table.data = buf;
+	fake_table.maxlen = sizeof(buf);
+
+	return proc_dostring(&fake_table, write, buffer, lenp, ppos);
+}
+
+static int lrng_proc_do_entropy(struct ctl_table *table, int write,
+				void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	struct ctl_table fake_table;
+	int entropy_count;
+
+	entropy_count = lrng_avail_entropy();
+
+	fake_table.data = &entropy_count;
+	fake_table.maxlen = sizeof(entropy_count);
+
+	return proc_dointvec(&fake_table, write, buffer, lenp, ppos);
+}
+
+static int lrng_sysctl_poolsize = LRNG_POOL_SIZE_BITS;
+static int lrng_min_read_thresh = LRNG_POOL_WORD_BITS;
+static int lrng_min_write_thresh;
+static int lrng_max_read_thresh = LRNG_POOL_SIZE_BITS;
+static int lrng_max_write_thresh = LRNG_POOL_SIZE_BITS;
+static char lrng_sysctl_bootid[16];
+static int lrng_sdrng_reseed_max_min;
+
+extern struct ctl_table random_table[];
+struct ctl_table random_table[] = {
+	{
+		.procname	= "poolsize",
+		.data		= &lrng_sysctl_poolsize,
+		.maxlen		= sizeof(int),
+		.mode		= 0444,
+		.proc_handler	= proc_dointvec,
+	},
+	{
+		.procname	= "entropy_avail",
+		.maxlen		= sizeof(int),
+		.mode		= 0444,
+		.proc_handler	= lrng_proc_do_entropy,
+	},
+	{
+		.procname	= "read_wakeup_threshold",
+		.data		= &lrng_read_wakeup_bits,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec_minmax,
+		.extra1		= &lrng_min_read_thresh,
+		.extra2		= &lrng_max_read_thresh,
+	},
+	{
+		.procname	= "write_wakeup_threshold",
+		.data		= &lrng_write_wakeup_bits,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec_minmax,
+		.extra1		= &lrng_min_write_thresh,
+		.extra2		= &lrng_max_write_thresh,
+	},
+	{
+		.procname	= "boot_id",
+		.data		= &lrng_sysctl_bootid,
+		.maxlen		= 16,
+		.mode		= 0444,
+		.proc_handler	= lrng_proc_do_uuid,
+	},
+	{
+		.procname	= "uuid",
+		.maxlen		= 16,
+		.mode		= 0444,
+		.proc_handler	= lrng_proc_do_uuid,
+	},
+	{
+		.procname       = "urandom_min_reseed_secs",
+		.data           = &lrng_sdrng_reseed_max_time,
+		.maxlen         = sizeof(int),
+		.mode           = 0644,
+		.proc_handler   = proc_dointvec,
+		.extra1		= &lrng_sdrng_reseed_max_min,
+	},
+	{
+		.procname	= "lrng_type",
+		.maxlen		= 30,
+		.mode		= 0444,
+		.proc_handler	= lrng_proc_do_type,
+	},
+	{ }
+};
-- 
2.23.0





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v25 04/12] LRNG - add switchable DRNG support
  2019-11-16  9:32 ` [PATCH v25 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                     ` (2 preceding siblings ...)
  2019-11-16  9:34   ` [PATCH v25 03/12] LRNG - /proc interface Stephan Müller
@ 2019-11-16  9:34   ` Stephan Müller
  2019-11-16  9:35   ` [PATCH v25 05/12] crypto: DRBG - externalize DRBG functions for LRNG Stephan Müller
                     ` (8 subsequent siblings)
  12 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-16  9:34 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

The DRNG switch support allows replacing the DRNG mechanism of the
LRNG. The switching support rests on the interface definition of
include/linux/lrng.h. A new DRNG is implemented by filling in the
interface defined in this header file.

In addition to the DRNG, the extension also has to provide a hash
implementation that is used to hash the entropy pool for random number
extraction.

Note: It is permissible to implement a DRNG whose operations may sleep.
However, the hash function must not sleep.

The switchable DRNG support allows replacing the DRNG at runtime.
However, only one DRNG extension is allowed to be loaded at any given
time. Before replacing it with another DRNG implementation, the possibly
existing DRNG extension must be unloaded.

The switchable DRNG extension activates the new DRNG during load time.
It is expected, however, that such a DRNG switch would be done only once
by an administrator to load the intended DRNG implementation.

It is permissible to compile DRNG extensions either as kernel modules or
statically. The initialization of the DRNG extension should be performed
with a late_initcall to ensure the extension is available when user
space starts but after all other initialization completed.
The initialization is performed by registering the function call data
structure with the lrng_set_drng_cb function. In order to unload the
DRNG extension, lrng_set_drng_cb must be invoked with the NULL
parameter.

The DRNG extension should always provide a security strength that is at
least as strong as LRNG_DRNG_SECURITY_STRENGTH_BITS.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Kconfig       |   7 ++
 drivers/char/lrng/Makefile      |   1 +
 drivers/char/lrng/lrng_switch.c | 185 ++++++++++++++++++++++++++++++++
 3 files changed, 193 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_switch.c

diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
index 1ba10fd421f3..c6e8eafd836c 100644
--- a/drivers/char/lrng/Kconfig
+++ b/drivers/char/lrng/Kconfig
@@ -52,4 +52,11 @@ config LRNG_POOL_SIZE
 	default 4 if LRNG_POOL_SIZE_65536
 	default 5 if LRNG_POOL_SIZE_131072
 
+menuconfig LRNG_DRNG_SWITCH
+	bool "Support DRNG runtime switching"
+	help
+	  The Linux RNG per default uses a ChaCha20 DRNG that is
+	  accessible via the external interfaces. With this configuration
+	  option other DRNGs can be selected and loaded at runtime.
+
 endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index b6240b73e33d..6bac97638767 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -10,3 +10,4 @@ obj-y				+= lrng_pool.o lrng_aux.o \
 
 obj-$(CONFIG_NUMA)		+= lrng_numa.o
 obj-$(CONFIG_SYSCTL)		+= lrng_proc.o
+obj-$(CONFIG_LRNG_DRNG_SWITCH)	+= lrng_switch.o
diff --git a/drivers/char/lrng/lrng_switch.c b/drivers/char/lrng/lrng_switch.c
new file mode 100644
index 000000000000..1e91a0d6df08
--- /dev/null
+++ b/drivers/char/lrng/lrng_switch.c
@@ -0,0 +1,185 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG DRNG switching support
+ *
+ * Copyright (C) 2016 - 2019, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/lrng.h>
+
+#include "lrng_internal.h"
+
+static void lrng_sdrng_switch(struct lrng_sdrng *sdrng_store,
+			      const struct lrng_crypto_cb *cb, int node)
+{
+	const struct lrng_crypto_cb *old_cb;
+	unsigned long flags = 0;
+	int ret;
+	u8 seed[LRNG_DRNG_SECURITY_STRENGTH_BYTES];
+	void *new_sdrng =
+			cb->lrng_drng_alloc(LRNG_DRNG_SECURITY_STRENGTH_BYTES);
+	void *old_sdrng, *new_hash = NULL, *old_hash = NULL;
+	bool sl = false, reset_sdrng = !lrng_get_available();
+
+	if (IS_ERR(new_sdrng)) {
+		pr_warn("could not allocate new secondary DRNG for NUMA node "
+			"%d (%ld)\n", node, PTR_ERR(new_sdrng));
+		return;
+	}
+
+#ifndef CONFIG_LRNG_TRNG_SUPPORT
+	new_hash = cb->lrng_hash_alloc(seed, sizeof(seed));
+#endif	/* CONFIG_LRNG_TRNG_SUPPORT */
+	if (IS_ERR(new_hash)) {
+		pr_warn("could not allocate new LRNG pool hash (%ld)\n",
+			PTR_ERR(new_hash));
+		cb->lrng_drng_dealloc(new_sdrng);
+		return;
+	}
+
+	lrng_sdrng_lock(sdrng_store, &flags);
+
+	/*
+	 * Pull from existing DRNG to seed new DRNG regardless of seed status
+	 * of old DRNG -- the entropy state for the secondary DRNG is left
+	 * unchanged which implies that als the new DRNG is reseeded when deemed
+	 * necessary. This seeding of the new DRNG shall only ensure that the
+	 * new DRNG has the same entropy as the old DRNG.
+	 */
+	ret = sdrng_store->crypto_cb->lrng_drng_generate_helper(
+				sdrng_store->sdrng, seed, sizeof(seed));
+	lrng_sdrng_unlock(sdrng_store, &flags);
+
+	if (ret < 0) {
+		reset_sdrng = true;
+		pr_warn("getting random data from secondary DRNG failed for "
+			"NUMA node %d (%d)\n", node, ret);
+	} else {
+		/* seed new DRNG with data */
+		ret = cb->lrng_drng_seed_helper(new_sdrng, seed, ret);
+		if (ret < 0) {
+			reset_sdrng = true;
+			pr_warn("seeding of new secondary DRNG failed for NUMA "
+				"node %d (%d)\n", node, ret);
+		} else {
+			pr_debug("seeded new secondary DRNG of NUMA node %d "
+				 "instance from old secondary DRNG instance\n",
+				 node);
+		}
+	}
+
+	mutex_lock(&sdrng_store->lock);
+	/*
+	 * If we switch the secondary DRNG from the initial ChaCha20 DRNG to
+	 * something else, there is a lock transition from spin lock to mutex
+	 * (see lrng_sdrng_is_atomic and how the lock is taken in
+	 * lrng_sdrng_lock). Thus, we need to take both locks during the
+	 * transition phase.
+	 */
+	if (lrng_sdrng_is_atomic(sdrng_store)) {
+		spin_lock_irqsave(&sdrng_store->spin_lock, flags);
+		sl = true;
+	}
+
+	if (reset_sdrng)
+		lrng_sdrng_reset(sdrng_store);
+
+	old_sdrng = sdrng_store->sdrng;
+	old_cb = sdrng_store->crypto_cb;
+	sdrng_store->sdrng = new_sdrng;
+	sdrng_store->crypto_cb = cb;
+
+	if (new_hash) {
+		old_hash = sdrng_store->hash;
+		sdrng_store->hash = new_hash;
+		pr_info("Entropy pool read-hash allocated for DRNG for NUMA "
+			"node %d\n", node);
+	}
+
+	if (sl)
+		spin_unlock_irqrestore(&sdrng_store->spin_lock, flags);
+	mutex_unlock(&sdrng_store->lock);
+
+	/* Secondary ChaCha20 serves as atomic instance left untouched. */
+	if (old_sdrng != &secondary_chacha20) {
+		old_cb->lrng_drng_dealloc(old_sdrng);
+		if (old_hash)
+			old_cb->lrng_hash_dealloc(old_hash);
+	}
+
+	pr_info("secondary DRNG of NUMA node %d switched\n", node);
+}
+
+/**
+ * Switch the existing DRNG instances with new using the new crypto callbacks.
+ * The caller must hold the lrng_crypto_cb_update lock.
+ */
+static int lrng_drngs_switch(const struct lrng_crypto_cb *cb)
+{
+	struct lrng_sdrng **lrng_sdrng = lrng_sdrng_instances();
+	struct lrng_sdrng *lrng_sdrng_init = lrng_sdrng_init_instance();
+	int ret = lrng_trng_switch(cb);
+
+	if (ret)
+		return ret;
+
+	/* Update secondary DRNG */
+	if (lrng_sdrng) {
+		u32 node;
+
+		for_each_online_node(node) {
+			if (lrng_sdrng[node])
+				lrng_sdrng_switch(lrng_sdrng[node], cb, node);
+		}
+	} else
+		lrng_sdrng_switch(lrng_sdrng_init, cb, 0);
+
+	lrng_set_available();
+
+	return 0;
+}
+
+/**
+ * lrng_set_drng_cb - Register new cryptographic callback functions for DRNG
+ * The registering implies that all old DRNG states are replaced with new
+ * DRNG states.
+ * @cb: Callback functions to be registered -- if NULL, use the default
+ *	callbacks pointing to the ChaCha20 DRNG.
+ * @return: 0 on success, < 0 on error
+ */
+int lrng_set_drng_cb(const struct lrng_crypto_cb *cb)
+{
+	struct lrng_sdrng *lrng_sdrng_init = lrng_sdrng_init_instance();
+	int ret;
+
+	if (!cb)
+		cb = &lrng_cc20_crypto_cb;
+
+	mutex_lock(&lrng_crypto_cb_update);
+
+	/*
+	 * If a callback other than the default is set, allow it only to be
+	 * set back to the default callback. This ensures that multiple
+	 * different callbacks can be registered at the same time. If a
+	 * callback different from the current callback and the default
+	 * callback shall be set, the current callback must be deregistered
+	 * (e.g. the kernel module providing it must be unloaded) and the new
+	 * implementation can be registered.
+	 */
+	if ((cb != &lrng_cc20_crypto_cb) &&
+	    (lrng_sdrng_init->crypto_cb != &lrng_cc20_crypto_cb)) {
+		pr_warn("disallow setting new cipher callbacks, unload the old "
+			"callbacks first!\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	ret = lrng_drngs_switch(cb);
+
+out:
+	mutex_unlock(&lrng_crypto_cb_update);
+	return ret;
+}
+EXPORT_SYMBOL(lrng_set_drng_cb);
-- 
2.23.0





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v25 05/12] crypto: DRBG - externalize DRBG functions for LRNG
  2019-11-16  9:32 ` [PATCH v25 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                     ` (3 preceding siblings ...)
  2019-11-16  9:34   ` [PATCH v25 04/12] LRNG - add switchable DRNG support Stephan Müller
@ 2019-11-16  9:35   ` Stephan Müller
  2019-11-16  9:35   ` [PATCH v25 06/12] LRNG - add SP800-90A DRBG extension Stephan Müller
                     ` (7 subsequent siblings)
  12 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-16  9:35 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

This patch allows several DRBG functions to be called by the LRNG kernel
code paths outside the drbg.c file.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 crypto/drbg.c         | 16 ++++++++++------
 include/crypto/drbg.h |  7 +++++++
 2 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/crypto/drbg.c b/crypto/drbg.c
index b6929eb5f565..5561dd0f09e1 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -113,7 +113,7 @@
  * the SHA256 / AES 256 over other ciphers. Thus, the favored
  * DRBGs are the latest entries in this array.
  */
-static const struct drbg_core drbg_cores[] = {
+const struct drbg_core drbg_cores[] = {
 #ifdef CONFIG_CRYPTO_DRBG_CTR
 	{
 		.flags = DRBG_CTR | DRBG_STRENGTH128,
@@ -190,6 +190,7 @@ static const struct drbg_core drbg_cores[] = {
 	},
 #endif /* CONFIG_CRYPTO_DRBG_HMAC */
 };
+EXPORT_SYMBOL(drbg_cores);
 
 static int drbg_uninstantiate(struct drbg_state *drbg);
 
@@ -205,7 +206,7 @@ static int drbg_uninstantiate(struct drbg_state *drbg);
  * Return: normalized strength in *bytes* value or 32 as default
  *	   to counter programming errors
  */
-static inline unsigned short drbg_sec_strength(drbg_flag_t flags)
+unsigned short drbg_sec_strength(drbg_flag_t flags)
 {
 	switch (flags & DRBG_STRENGTH_MASK) {
 	case DRBG_STRENGTH128:
@@ -218,6 +219,7 @@ static inline unsigned short drbg_sec_strength(drbg_flag_t flags)
 		return 32;
 	}
 }
+EXPORT_SYMBOL(drbg_sec_strength);
 
 /*
  * FIPS 140-2 continuous self test for the noise source
@@ -1202,7 +1204,7 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
 }
 
 /* Free all substructures in a DRBG state without the DRBG state structure */
-static inline void drbg_dealloc_state(struct drbg_state *drbg)
+void drbg_dealloc_state(struct drbg_state *drbg)
 {
 	if (!drbg)
 		return;
@@ -1223,12 +1225,13 @@ static inline void drbg_dealloc_state(struct drbg_state *drbg)
 		drbg->fips_primed = false;
 	}
 }
+EXPORT_SYMBOL(drbg_dealloc_state);
 
 /*
  * Allocate all sub-structures for a DRBG state.
  * The DRBG state structure must already be allocated.
  */
-static inline int drbg_alloc_state(struct drbg_state *drbg)
+int drbg_alloc_state(struct drbg_state *drbg)
 {
 	int ret = -ENOMEM;
 	unsigned int sb_size = 0;
@@ -1307,6 +1310,7 @@ static inline int drbg_alloc_state(struct drbg_state *drbg)
 	drbg_dealloc_state(drbg);
 	return ret;
 }
+EXPORT_SYMBOL(drbg_alloc_state);
 
 /*************************************************************************
  * DRBG interface functions
@@ -1874,8 +1878,7 @@ static int drbg_kcapi_sym_ctr(struct drbg_state *drbg,
  *
  * return: flags
  */
-static inline void drbg_convert_tfm_core(const char *cra_driver_name,
-					 int *coreref, bool *pr)
+void drbg_convert_tfm_core(const char *cra_driver_name, int *coreref, bool *pr)
 {
 	int i = 0;
 	size_t start = 0;
@@ -1902,6 +1905,7 @@ static inline void drbg_convert_tfm_core(const char *cra_driver_name,
 		}
 	}
 }
+EXPORT_SYMBOL(drbg_convert_tfm_core);
 
 static int drbg_kcapi_init(struct crypto_tfm *tfm)
 {
diff --git a/include/crypto/drbg.h b/include/crypto/drbg.h
index 8c9af21efce1..c63b20375235 100644
--- a/include/crypto/drbg.h
+++ b/include/crypto/drbg.h
@@ -282,4 +282,11 @@ enum drbg_prefixes {
 	DRBG_PREFIX3
 };
 
+extern int drbg_alloc_state(struct drbg_state *drbg);
+extern void drbg_dealloc_state(struct drbg_state *drbg);
+extern void drbg_convert_tfm_core(const char *cra_driver_name, int *coreref,
+				  bool *pr);
+extern const struct drbg_core drbg_cores[];
+extern unsigned short drbg_sec_strength(drbg_flag_t flags);
+
 #endif /* _DRBG_H */
-- 
2.23.0





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v25 06/12] LRNG - add SP800-90A DRBG extension
  2019-11-16  9:32 ` [PATCH v25 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                     ` (4 preceding siblings ...)
  2019-11-16  9:35   ` [PATCH v25 05/12] crypto: DRBG - externalize DRBG functions for LRNG Stephan Müller
@ 2019-11-16  9:35   ` Stephan Müller
  2019-11-16  9:35   ` [PATCH v25 07/12] LRNG - add kernel crypto API PRNG extension Stephan Müller
                     ` (6 subsequent siblings)
  12 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-16  9:35 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

Using the LRNG switchable DRNG support, the SP800-90A DRBG extension is
implemented.

The DRBG uses the kernel crypto API DRBG implementation. In addition, it
uses the kernel crypto API SHASH support to provide the hashing
operation.

The DRBG supports the choice of either a CTR DRBG using AES-256, HMAC
DRBG with SHA-512 core or Hash DRBG with SHA-512 core. The used core can
be selected with the module parameter lrng_drbg_type. The default is the
CTR DRBG.

When compiling the DRBG extension statically, the DRBG is loaded at
late_initcall stage which implies that with the start of user space, the
user space interfaces of getrandom(2), /dev/random and /dev/urandom
provide random data produced by an SP800-90A DRBG.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Kconfig     |  11 ++
 drivers/char/lrng/Makefile    |   1 +
 drivers/char/lrng/lrng_drbg.c | 261 ++++++++++++++++++++++++++++++++++
 3 files changed, 273 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_drbg.c

diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
index c6e8eafd836c..dcdf4ef83da5 100644
--- a/drivers/char/lrng/Kconfig
+++ b/drivers/char/lrng/Kconfig
@@ -59,4 +59,15 @@ menuconfig LRNG_DRNG_SWITCH
 	  accessible via the external interfaces. With this configuration
 	  option other DRNGs can be selected and loaded at runtime.
 
+if LRNG_DRNG_SWITCH
+config LRNG_DRBG
+	tristate "SP800-90A support for the LRNG"
+	select CRYPTO_DRBG_MENU
+	select CRYPTO_CMAC if CRYPTO_DRBG_CTR
+	help
+	  Enable the SP800-90A DRBG support for the LRNG. Once the
+	  module is loaded, output from /dev/random, /dev/urandom,
+	  getrandom(2), or get_random_bytes is provided by a DRBG.
+endif # LRNG_DRNG_SWITCH
+
 endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index 6bac97638767..e3a704b3466c 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -11,3 +11,4 @@ obj-y				+= lrng_pool.o lrng_aux.o \
 obj-$(CONFIG_NUMA)		+= lrng_numa.o
 obj-$(CONFIG_SYSCTL)		+= lrng_proc.o
 obj-$(CONFIG_LRNG_DRNG_SWITCH)	+= lrng_switch.o
+obj-$(CONFIG_LRNG_DRBG)		+= lrng_drbg.o
diff --git a/drivers/char/lrng/lrng_drbg.c b/drivers/char/lrng/lrng_drbg.c
new file mode 100644
index 000000000000..3b5314f399a2
--- /dev/null
+++ b/drivers/char/lrng/lrng_drbg.c
@@ -0,0 +1,261 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * Backend for the LRNG providing the cryptographic primitives using the
+ * kernel crypto API and its DRBG.
+ *
+ * Copyright (C) 2016 - 2019, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <crypto/drbg.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/lrng.h>
+
+/*
+ * Define a DRBG plus a hash / MAC used to extract data from the entropy pool.
+ * For LRNG_HASH_NAME you can use a hash or a MAC (HMAC or CMAC) of your choice
+ * (Note, you should use the suggested selections below -- using SHA-1 or MD5
+ * is not wise). The idea is that the used cipher primitive can be selected to
+ * be the same as used for the DRBG. I.e. the LRNG only uses one cipher
+ * primitive using the same cipher implementation with the options offered in
+ * the following. This means, if the CTR DRBG is selected and AES-NI is present,
+ * both the CTR DRBG and the selected cmac(aes) use AES-NI.
+ *
+ * The security strengths of the DRBGs are all 256 bits according to
+ * SP800-57 section 5.6.1.
+ *
+ * This definition is allowed to be changed.
+ */
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+static unsigned int lrng_drbg_type = 0;
+#elif defined CONFIG_CRYPTO_DRBG_HMAC
+static unsigned int lrng_drbg_type = 1;
+#elif defined CONFIG_CRYPTO_DRBG_HASH
+static unsigned int lrng_drbg_type = 2;
+#else
+#error "Unknown DRBG in use"
+#endif
+
+/* The parameter must be r/o in sysfs as otherwise races appear. */
+module_param(lrng_drbg_type, uint, 0444);
+MODULE_PARM_DESC(lrng_drbg_type, "DRBG type used for LRNG (0->CTR_DRBG, "
+				 "1->HMAC_DRBG, 2->Hash_DRBG)");
+
+struct lrng_drbg {
+	const char *hash_name;
+	const char *drbg_core;
+};
+
+static const struct lrng_drbg lrng_drbg_types[] = {
+	{	/* CTR_DRBG with AES-256 using derivation function */
+		.hash_name = "cmac(aes)",
+		.drbg_core = "drbg_nopr_ctr_aes256",
+	}, {	/* HMAC_DRBG with SHA-512 */
+		.hash_name = "sha512",
+		.drbg_core = "drbg_nopr_hmac_sha512",
+	}, {	/* Hash_DRBG with SHA-512 using derivation function */
+		.hash_name = "sha512",
+		.drbg_core = "drbg_nopr_sha512"
+	}
+};
+
+struct lrng_hash_info {
+	struct shash_desc shash;
+	char ctx[];
+};
+
+static int lrng_drbg_drng_seed_helper(void *drng, const u8 *inbuf, u32 inbuflen)
+{
+	struct drbg_state *drbg = (struct drbg_state *)drng;
+	LIST_HEAD(seedlist);
+	struct drbg_string data;
+	int ret;
+
+	drbg_string_fill(&data, inbuf, inbuflen);
+	list_add_tail(&data.list, &seedlist);
+	ret = drbg->d_ops->update(drbg, &seedlist, drbg->seeded);
+
+	if (ret >= 0)
+		drbg->seeded = true;
+
+	return ret;
+}
+
+static int lrng_drbg_drng_generate_helper(void *drng, u8 *outbuf, u32 outbuflen)
+{
+	struct drbg_state *drbg = (struct drbg_state *)drng;
+
+	return drbg->d_ops->generate(drbg, outbuf, outbuflen, NULL);
+}
+
+static void *lrng_drbg_drng_alloc(u32 sec_strength)
+{
+	struct drbg_state *drbg;
+	int coreref = -1;
+	bool pr = false;
+	int ret;
+
+	drbg_convert_tfm_core(lrng_drbg_types[lrng_drbg_type].drbg_core,
+			      &coreref, &pr);
+	if (coreref < 0)
+		return ERR_PTR(-EFAULT);
+
+	drbg = kzalloc(sizeof(struct drbg_state), GFP_KERNEL);
+	if (!drbg)
+		return ERR_PTR(-ENOMEM);
+
+	drbg->core = &drbg_cores[coreref];
+	drbg->seeded = false;
+	ret = drbg_alloc_state(drbg);
+	if (ret)
+		goto err;
+
+	if (sec_strength > drbg_sec_strength(drbg->core->flags)) {
+		pr_err("Security strength of DRBG (%u bits) lower than "
+		       "requested by LRNG (%u bits)\n",
+			drbg_sec_strength(drbg->core->flags) * 8,
+			sec_strength * 8);
+		goto dealloc;
+	}
+
+	if (sec_strength < drbg_sec_strength(drbg->core->flags))
+		pr_warn("Security strength of DRBG (%u bits) higher than "
+			"requested by LRNG (%u bits)\n",
+			drbg_sec_strength(drbg->core->flags) * 8,
+			sec_strength * 8);
+
+	pr_info("DRBG with %s core allocated\n", drbg->core->backend_cra_name);
+
+	return drbg;
+
+dealloc:
+	if (drbg->d_ops)
+		drbg->d_ops->crypto_fini(drbg);
+	drbg_dealloc_state(drbg);
+err:
+	kfree(drbg);
+	return ERR_PTR(-EINVAL);
+}
+
+static void lrng_drbg_drng_dealloc(void *drng)
+{
+	struct drbg_state *drbg = (struct drbg_state *)drng;
+
+	drbg_dealloc_state(drbg);
+	kzfree(drbg);
+	pr_info("DRBG deallocated\n");
+}
+
+static void *lrng_drbg_hash_alloc(const u8 *key, u32 keylen)
+{
+	struct lrng_hash_info *lrng_hash;
+	struct crypto_shash *tfm;
+	int size, ret;
+
+	tfm = crypto_alloc_shash(lrng_drbg_types[lrng_drbg_type].hash_name,
+				 0, 0);
+	if (IS_ERR(tfm)) {
+		pr_err("could not allocate hash %s\n",
+		       lrng_drbg_types[lrng_drbg_type].hash_name);
+		return ERR_CAST(tfm);
+	}
+
+	size = sizeof(struct lrng_hash_info) + crypto_shash_descsize(tfm);
+	lrng_hash = kmalloc(size, GFP_KERNEL);
+	if (!lrng_hash) {
+		crypto_free_shash(tfm);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	lrng_hash->shash.tfm = tfm;
+
+	/* If the used hash is no MAC, ignore the ENOSYS return code */
+	ret = crypto_shash_setkey(tfm, key, keylen);
+	if (ret && ret != -ENOSYS) {
+		pr_err("could not set the key for MAC\n");
+		crypto_free_shash(tfm);
+		kfree(lrng_hash);
+		return ERR_PTR(ret);
+	}
+
+	pr_info("Hash %s allocated\n",
+		lrng_drbg_types[lrng_drbg_type].hash_name);
+
+	return lrng_hash;
+}
+
+static void lrng_drbg_hash_dealloc(void *hash)
+{
+	struct lrng_hash_info *lrng_hash = (struct lrng_hash_info *)hash;
+	struct shash_desc *shash = &lrng_hash->shash;
+	struct crypto_shash *tfm = shash->tfm;
+
+	crypto_free_shash(tfm);
+	kfree(lrng_hash);
+	pr_info("Hash deallocated\n");
+}
+
+static u32 lrng_drbg_hash_digestsize(void *hash)
+{
+	struct lrng_hash_info *lrng_hash = (struct lrng_hash_info *)hash;
+	struct shash_desc *shash = &lrng_hash->shash;
+
+	return crypto_shash_digestsize(shash->tfm);
+}
+
+static int lrng_drbg_hash_buffer(void *hash, const u8 *inbuf, u32 inbuflen,
+				 u8 *digest)
+{
+	struct lrng_hash_info *lrng_hash = (struct lrng_hash_info *)hash;
+	struct shash_desc *shash = &lrng_hash->shash;
+
+	return crypto_shash_digest(shash, inbuf, inbuflen, digest);
+}
+
+static const char *lrng_drbg_name(void)
+{
+	return lrng_drbg_types[lrng_drbg_type].drbg_core;
+}
+
+static const char *lrng_hash_name(void)
+{
+	return lrng_drbg_types[lrng_drbg_type].hash_name;
+}
+
+const static struct lrng_crypto_cb lrng_drbg_crypto_cb = {
+	.lrng_drng_name			= lrng_drbg_name,
+	.lrng_hash_name			= lrng_hash_name,
+	.lrng_drng_alloc		= lrng_drbg_drng_alloc,
+	.lrng_drng_dealloc		= lrng_drbg_drng_dealloc,
+	.lrng_drng_seed_helper		= lrng_drbg_drng_seed_helper,
+	.lrng_drng_generate_helper	= lrng_drbg_drng_generate_helper,
+	.lrng_drng_generate_helper_full	= lrng_drbg_drng_generate_helper,
+	.lrng_hash_alloc		= lrng_drbg_hash_alloc,
+	.lrng_hash_dealloc		= lrng_drbg_hash_dealloc,
+	.lrng_hash_digestsize		= lrng_drbg_hash_digestsize,
+	.lrng_hash_buffer		= lrng_drbg_hash_buffer,
+};
+
+static int __init lrng_drbg_init(void)
+{
+	if (lrng_drbg_type >= ARRAY_SIZE(lrng_drbg_types)) {
+		pr_err("lrng_drbg_type parameter too large (given %u - max: %lu)",
+		       lrng_drbg_type,
+		       (unsigned long)ARRAY_SIZE(lrng_drbg_types) - 1);
+		return -EAGAIN;
+	}
+	return lrng_set_drng_cb(&lrng_drbg_crypto_cb);
+}
+
+static void __exit lrng_drbg_exit(void)
+{
+	lrng_set_drng_cb(NULL);
+}
+
+late_initcall(lrng_drbg_init);
+module_exit(lrng_drbg_exit);
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
+MODULE_DESCRIPTION("Linux Random Number Generator - SP800-90A DRBG backend");
-- 
2.23.0





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v25 07/12] LRNG - add kernel crypto API PRNG extension
  2019-11-16  9:32 ` [PATCH v25 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                     ` (5 preceding siblings ...)
  2019-11-16  9:35   ` [PATCH v25 06/12] LRNG - add SP800-90A DRBG extension Stephan Müller
@ 2019-11-16  9:35   ` Stephan Müller
  2019-11-16  9:36   ` [PATCH v25 08/12] crypto: provide access to a static Jitter RNG state Stephan Müller
                     ` (5 subsequent siblings)
  12 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-16  9:35 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

Add runtime-pluggable support for all PRNGs that are accessible via
the kernel crypto API, including hardware PRNGs. The PRNG is selected
with the module parameter drng_name where the name must be one that the
kernel crypto API can resolve into an RNG.

This allows using of the kernel crypto API PRNG implementations that
provide an interface to hardware PRNGs. Using this extension,
the LRNG uses the hardware PRNGs to generate random numbers. An
example is the S390 CPACF support providing such a PRNG.

The hash is provided by a kernel crypto API SHASH whose digest size
complies with the seedsize of the PRNG.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Kconfig      |  10 +
 drivers/char/lrng/Makefile     |   1 +
 drivers/char/lrng/lrng_kcapi.c | 328 +++++++++++++++++++++++++++++++++
 3 files changed, 339 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_kcapi.c

diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
index dcdf4ef83da5..03e6e2ec356b 100644
--- a/drivers/char/lrng/Kconfig
+++ b/drivers/char/lrng/Kconfig
@@ -68,6 +68,16 @@ config LRNG_DRBG
 	  Enable the SP800-90A DRBG support for the LRNG. Once the
 	  module is loaded, output from /dev/random, /dev/urandom,
 	  getrandom(2), or get_random_bytes is provided by a DRBG.
+
+config LRNG_KCAPI
+	tristate "Kernel Crypto API support for the LRNG"
+	select CRYPTO_RNG
+	help
+	  Enable the support for generic pseudo-random number
+	  generators offered by the kernel crypto API with the
+	  LRNG. Once the module is loaded, output from /dev/random,
+	  /dev/urandom, getrandom(2), or get_random_bytes is
+	  provided by the selected kernel crypto API RNG.
 endif # LRNG_DRNG_SWITCH
 
 endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index e3a704b3466c..027b6ea51c20 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -12,3 +12,4 @@ obj-$(CONFIG_NUMA)		+= lrng_numa.o
 obj-$(CONFIG_SYSCTL)		+= lrng_proc.o
 obj-$(CONFIG_LRNG_DRNG_SWITCH)	+= lrng_switch.o
 obj-$(CONFIG_LRNG_DRBG)		+= lrng_drbg.o
+obj-$(CONFIG_LRNG_KCAPI)	+= lrng_kcapi.o
diff --git a/drivers/char/lrng/lrng_kcapi.c b/drivers/char/lrng/lrng_kcapi.c
new file mode 100644
index 000000000000..f887447e524d
--- /dev/null
+++ b/drivers/char/lrng/lrng_kcapi.c
@@ -0,0 +1,328 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * Backend for the LRNG providing the cryptographic primitives using the
+ * kernel crypto API.
+ *
+ * Copyright (C) 2018 - 2019, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <crypto/hash.h>
+#include <crypto/rng.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/lrng.h>
+
+static char *drng_name = NULL;
+module_param(drng_name, charp, 0444);
+MODULE_PARM_DESC(drng_name, "Kernel crypto API name of DRNG");
+
+static char *pool_hash = "sha512";
+module_param(pool_hash, charp, 0444);
+MODULE_PARM_DESC(pool_hash,
+		 "Kernel crypto API name of hash or keyed message digest to read the entropy pool");
+
+static char *seed_hash = NULL;
+module_param(seed_hash, charp, 0444);
+MODULE_PARM_DESC(seed_hash,
+		 "Kernel crypto API name of hash with output size equal to seedsize of DRNG to bring seed string to the size required by the DRNG");
+
+struct lrng_hash_info {
+	struct shash_desc shash;
+	char ctx[];
+};
+
+struct lrng_drng_info {
+	struct crypto_rng *kcapi_rng;
+	struct lrng_hash_info *lrng_hash;
+};
+
+static struct lrng_hash_info *_lrng_kcapi_hash_alloc(const char *name)
+{
+	struct lrng_hash_info *lrng_hash;
+	struct crypto_shash *tfm;
+	int size;
+
+	if (!name) {
+		pr_err("Hash name missing\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	tfm = crypto_alloc_shash(name, 0, 0);
+	if (IS_ERR(tfm)) {
+		pr_err("could not allocate hash %s\n", name);
+		return ERR_CAST(tfm);
+	}
+
+	size = sizeof(struct lrng_hash_info) + crypto_shash_descsize(tfm);
+	lrng_hash = kmalloc(size, GFP_KERNEL);
+	if (!lrng_hash) {
+		crypto_free_shash(tfm);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	lrng_hash->shash.tfm = tfm;
+
+	return lrng_hash;
+}
+
+static inline u32 _lrng_kcapi_hash_digestsize(struct lrng_hash_info *lrng_hash)
+{
+	struct shash_desc *shash = &lrng_hash->shash;
+	struct crypto_shash *tfm = shash->tfm;
+
+	return crypto_shash_digestsize(tfm);
+}
+
+static inline void _lrng_kcapi_hash_free(struct lrng_hash_info *lrng_hash)
+{
+	struct shash_desc *shash = &lrng_hash->shash;
+	struct crypto_shash *tfm = shash->tfm;
+
+	crypto_free_shash(tfm);
+	kfree(lrng_hash);
+}
+
+static void *lrng_kcapi_hash_alloc(const u8 *key, u32 keylen)
+{
+	struct lrng_hash_info *lrng_hash;
+	int ret;
+
+	lrng_hash = _lrng_kcapi_hash_alloc(pool_hash);
+	if (IS_ERR(lrng_hash))
+		return ERR_CAST(lrng_hash);
+
+	/* If the used hash is no MAC, ignore the ENOSYS return code */
+	ret = crypto_shash_setkey(lrng_hash->shash.tfm, key, keylen);
+	if (ret && ret != -ENOSYS) {
+		pr_err("could not set the key for MAC\n");
+		_lrng_kcapi_hash_free(lrng_hash);
+		return ERR_PTR(ret);
+	}
+
+	pr_info("Hash %s allocated\n", pool_hash);
+
+	return lrng_hash;
+}
+
+static void lrng_kcapi_hash_dealloc(void *hash)
+{
+	struct lrng_hash_info *lrng_hash = (struct lrng_hash_info *)hash;
+
+	_lrng_kcapi_hash_free(lrng_hash);
+	pr_info("Hash %s deallocated\n", pool_hash);
+}
+
+static u32 lrng_kcapi_hash_digestsize(void *hash)
+{
+	struct lrng_hash_info *lrng_hash = (struct lrng_hash_info *)hash;
+
+	return _lrng_kcapi_hash_digestsize(lrng_hash);
+}
+
+static int lrng_kcapi_hash_buffer(void *hash, const u8 *inbuf, u32 inbuflen,
+				  u8 *digest)
+{
+	struct lrng_hash_info *lrng_hash = (struct lrng_hash_info *)hash;
+	struct shash_desc *shash = &lrng_hash->shash;
+
+	return crypto_shash_digest(shash, inbuf, inbuflen, digest);
+}
+
+static int lrng_kcapi_drng_seed_helper(void *drng, const u8 *inbuf,
+				       u32 inbuflen)
+{
+	struct lrng_drng_info *lrng_drng_info = (struct lrng_drng_info *)drng;
+	struct crypto_rng *kcapi_rng = lrng_drng_info->kcapi_rng;
+	struct lrng_hash_info *lrng_hash = lrng_drng_info->lrng_hash;
+
+	if (lrng_hash) {
+		struct shash_desc *shash = &lrng_hash->shash;
+		u32 digestsize = _lrng_kcapi_hash_digestsize(lrng_hash);
+		u8 digest[64] __aligned(8);
+		int ret;
+
+		BUG_ON(digestsize > sizeof(digest));
+
+		ret = crypto_shash_digest(shash, inbuf, inbuflen, digest);
+		if (ret)
+			return ret;
+
+		ret = crypto_rng_reset(kcapi_rng, digest, digestsize);
+		if (ret)
+			return ret;
+
+		memzero_explicit(digest, digestsize);
+
+		return 0;
+	} else {
+		return crypto_rng_reset(kcapi_rng, inbuf, inbuflen);
+	}
+}
+
+static int lrng_kcapi_drng_generate_helper(void *drng, u8 *outbuf,
+					   u32 outbuflen)
+{
+	struct lrng_drng_info *lrng_drng_info = (struct lrng_drng_info *)drng;
+	struct crypto_rng *kcapi_rng = lrng_drng_info->kcapi_rng;
+	int ret = crypto_rng_get_bytes(kcapi_rng, outbuf, outbuflen);
+
+	if (ret < 0)
+		return ret;
+
+	return outbuflen;
+}
+
+static void *lrng_kcapi_drng_alloc(u32 sec_strength)
+{
+	struct lrng_drng_info *lrng_drng_info;
+	struct crypto_rng *kcapi_rng;
+	int seedsize;
+	void *ret =  ERR_PTR(-ENOMEM);
+
+	if (!drng_name) {
+		pr_err("DRNG name missing\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (!memcmp(drng_name, "drbg", 4)) {
+		pr_err("SP800-90A DRBG cannot be allocated using lrng_kcapi "
+		       "backend, use lrng_drbg backend instead\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (!memcmp(drng_name, "stdrng", 6)) {
+		pr_err("stdrng cannot be allocated using lrng_kcapi backend, "
+		       "it is too unspecific and potentially may allocate the "
+		       "DRBG\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	lrng_drng_info = kmalloc(sizeof(*lrng_drng_info), GFP_KERNEL);
+	if (!lrng_drng_info)
+		return ERR_PTR(-ENOMEM);
+
+	kcapi_rng = crypto_alloc_rng(drng_name, 0, 0);
+	if (IS_ERR(kcapi_rng)) {
+		pr_err("DRNG %s cannot be allocated\n", drng_name);
+		ret = ERR_CAST(kcapi_rng);
+		goto free;
+	}
+	lrng_drng_info->kcapi_rng = kcapi_rng;
+
+	seedsize =  crypto_rng_seedsize(kcapi_rng);
+
+	if (sec_strength > seedsize)
+		pr_info("Seedsize DRNG (%u bits) lower than "
+			"security strength of LRNG noise source (%u bits)\n",
+			crypto_rng_seedsize(kcapi_rng) * 8,
+			sec_strength * 8);
+
+	if (seedsize) {
+		struct lrng_hash_info *lrng_hash;
+
+		if (!seed_hash) {
+			switch (seedsize) {
+			case 32:
+				seed_hash = "sha256";
+				break;
+			case 48:
+				seed_hash = "sha384";
+				break;
+			case 64:
+				seed_hash = "sha512";
+				break;
+			default:
+				pr_err("Seed size %d cannot be processed\n",
+				       seedsize);
+				goto dealloc;
+				break;
+			}
+		}
+
+		lrng_hash = _lrng_kcapi_hash_alloc(seed_hash);
+		if (IS_ERR(lrng_hash)) {
+			ret = ERR_CAST(lrng_hash);
+			goto dealloc;
+		}
+
+		if (seedsize != _lrng_kcapi_hash_digestsize(lrng_hash)) {
+			pr_err("Seed hash output size not equal to DRNG seed "
+			       "size\n");
+			_lrng_kcapi_hash_free(lrng_hash);
+			ret = ERR_PTR(-EINVAL);
+			goto dealloc;
+		}
+
+		lrng_drng_info->lrng_hash = lrng_hash;
+
+		pr_info("Seed hash %s allocated\n", seed_hash);
+	} else {
+		lrng_drng_info->lrng_hash = NULL;
+	}
+
+	pr_info("Kernel crypto API DRNG %s allocated\n", drng_name);
+
+	return lrng_drng_info;
+
+dealloc:
+	crypto_free_rng(kcapi_rng);
+free:
+	kfree(lrng_drng_info);
+	return ret;
+}
+
+static void lrng_kcapi_drng_dealloc(void *drng)
+{
+	struct lrng_drng_info *lrng_drng_info = (struct lrng_drng_info *)drng;
+	struct crypto_rng *kcapi_rng = lrng_drng_info->kcapi_rng;
+	struct lrng_hash_info *lrng_hash = lrng_drng_info->lrng_hash;
+
+	crypto_free_rng(kcapi_rng);
+	if (lrng_hash) {
+		_lrng_kcapi_hash_free(lrng_hash);
+		pr_info("Seed hash %s deallocated\n", seed_hash);
+	}
+	kfree(lrng_drng_info);
+	pr_info("DRNG %s deallocated\n", drng_name);
+}
+
+static const char *lrng_kcapi_drng_name(void)
+{
+	return drng_name;
+}
+
+static const char *lrng_kcapi_pool_hash(void)
+{
+	return pool_hash;
+}
+
+const static struct lrng_crypto_cb lrng_kcapi_crypto_cb = {
+	.lrng_drng_name			= lrng_kcapi_drng_name,
+	.lrng_hash_name			= lrng_kcapi_pool_hash,
+	.lrng_drng_alloc		= lrng_kcapi_drng_alloc,
+	.lrng_drng_dealloc		= lrng_kcapi_drng_dealloc,
+	.lrng_drng_seed_helper		= lrng_kcapi_drng_seed_helper,
+	.lrng_drng_generate_helper	= lrng_kcapi_drng_generate_helper,
+	.lrng_drng_generate_helper_full	= lrng_kcapi_drng_generate_helper,
+	.lrng_hash_alloc		= lrng_kcapi_hash_alloc,
+	.lrng_hash_dealloc		= lrng_kcapi_hash_dealloc,
+	.lrng_hash_digestsize		= lrng_kcapi_hash_digestsize,
+	.lrng_hash_buffer		= lrng_kcapi_hash_buffer,
+};
+
+static int __init lrng_kcapi_init(void)
+{
+	return lrng_set_drng_cb(&lrng_kcapi_crypto_cb);
+}
+static void __exit lrng_kcapi_exit(void)
+{
+	lrng_set_drng_cb(NULL);
+}
+
+late_initcall(lrng_kcapi_init);
+module_exit(lrng_kcapi_exit);
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
+MODULE_DESCRIPTION("Linux Random Number Generator - kernel crypto API DRNG backend");
-- 
2.23.0





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v25 08/12] crypto: provide access to a static Jitter RNG state
  2019-11-16  9:32 ` [PATCH v25 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                     ` (6 preceding siblings ...)
  2019-11-16  9:35   ` [PATCH v25 07/12] LRNG - add kernel crypto API PRNG extension Stephan Müller
@ 2019-11-16  9:36   ` Stephan Müller
  2019-11-16  9:36   ` [PATCH v25 09/12] LRNG - add Jitter RNG fast noise source Stephan Müller
                     ` (4 subsequent siblings)
  12 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-16  9:36 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

To support the LRNG operation which uses the Jitter RNG separately
from the kernel crypto API, at a time where potentially the regular
memory management is not yet initialized, the Jitter RNG needs to
provide a state whose memory is defined at compile time. As only once
instance will ever be needed by the LRNG, define once static memory
block which is solely to be used by the LRNG.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 crypto/jitterentropy.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/crypto/jitterentropy.c b/crypto/jitterentropy.c
index 77fa2120fe0c..3a815495f778 100644
--- a/crypto/jitterentropy.c
+++ b/crypto/jitterentropy.c
@@ -644,3 +644,26 @@ int jent_entropy_init(void)
 
 	return 0;
 }
+
+struct rand_data *jent_lrng_entropy_collector(void)
+{
+	static unsigned char lrng_jent_mem[JENT_MEMORY_SIZE];
+	static struct rand_data lrng_jent_state = {
+		.data		= 0,
+		.old_data	= 0,
+		.prev_time	= 0,
+		.last_delta	= 0,
+		.last_delta2	= 0,
+		.osr		= 1,
+		.mem		= lrng_jent_mem,
+		.memlocation	= 0,
+		.memblocks	= JENT_MEMORY_BLOCKSIZE,
+		.memblocksize	= JENT_MEMORY_BLOCKS,
+		.memaccessloops	= JENT_MEMORY_ACCESSLOOPS,
+	};
+
+	if (jent_entropy_init())
+		return NULL;
+
+	return &lrng_jent_state;
+}
-- 
2.23.0





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v25 09/12] LRNG - add Jitter RNG fast noise source
  2019-11-16  9:32 ` [PATCH v25 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                     ` (7 preceding siblings ...)
  2019-11-16  9:36   ` [PATCH v25 08/12] crypto: provide access to a static Jitter RNG state Stephan Müller
@ 2019-11-16  9:36   ` Stephan Müller
  2019-11-20 13:33     ` Neil Horman
  2019-11-16  9:37   ` [PATCH v25 10/12] LRNG - add TRNG support Stephan Müller
                     ` (3 subsequent siblings)
  12 siblings, 1 reply; 162+ messages in thread
From: Stephan Müller @ 2019-11-16  9:36 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

The Jitter RNG fast noise source implemented as part of the kernel
crypto API is queried for 256 bits of entropy at the time the seed
buffer managed by the LRNG is about to be filled.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Kconfig     | 11 +++++
 drivers/char/lrng/Makefile    |  1 +
 drivers/char/lrng/lrng_jent.c | 88 +++++++++++++++++++++++++++++++++++
 3 files changed, 100 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_jent.c

diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
index 03e6e2ec356b..80fc723c67d2 100644
--- a/drivers/char/lrng/Kconfig
+++ b/drivers/char/lrng/Kconfig
@@ -80,4 +80,15 @@ config LRNG_KCAPI
 	  provided by the selected kernel crypto API RNG.
 endif # LRNG_DRNG_SWITCH
 
+config LRNG_JENT
+	bool "Enable Jitter RNG as LRNG Seed Source"
+	select CRYPTO_JITTERENTROPY
+	help
+	  The Linux RNG may use the Jitter RNG as noise source. Enabling
+	  this option enables the use of the Jitter RNG. Its default
+	  entropy level is 16 bits of entropy per 256 data bits delivered
+	  by the Jitter RNG. This entropy level can be changed at boot
+	  time or at runtime with the lrng_base.jitterrng configuration
+	  variable.
+
 endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index 027b6ea51c20..a87d800c9aae 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -13,3 +13,4 @@ obj-$(CONFIG_SYSCTL)		+= lrng_proc.o
 obj-$(CONFIG_LRNG_DRNG_SWITCH)	+= lrng_switch.o
 obj-$(CONFIG_LRNG_DRBG)		+= lrng_drbg.o
 obj-$(CONFIG_LRNG_KCAPI)	+= lrng_kcapi.o
+obj-$(CONFIG_LRNG_JENT)		+= lrng_jent.o
diff --git a/drivers/char/lrng/lrng_jent.c b/drivers/char/lrng/lrng_jent.c
new file mode 100644
index 000000000000..43114a44b8f5
--- /dev/null
+++ b/drivers/char/lrng/lrng_jent.c
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG Fast Noise Source: Jitter RNG
+ *
+ * Copyright (C) 2016 - 2019, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "lrng_internal.h"
+
+/*
+ * Estimated entropy of data is a 16th of LRNG_DRNG_SECURITY_STRENGTH_BITS.
+ * Albeit a full entropy assessment is provided for the noise source indicating
+ * that it provides high entropy rates and considering that it deactivates
+ * when it detects insufficient hardware, the chosen under estimation of
+ * entropy is considered to be acceptable to all reviewers.
+ */
+static u32 jitterrng = LRNG_DRNG_SECURITY_STRENGTH_BITS>>4;
+module_param(jitterrng, uint, 0644);
+MODULE_PARM_DESC(jitterrng, "Entropy in bits of 256 data bits from Jitter "
+			    "RNG noise source");
+
+/**
+ * Get Jitter RNG entropy
+ *
+ * @outbuf buffer to store entropy
+ * @outbuflen length of buffer
+ * @return > 0 on success where value provides the added entropy in bits
+ *	   0 if no fast source was available
+ */
+struct rand_data;
+struct rand_data *jent_lrng_entropy_collector(void);
+int jent_read_entropy(struct rand_data *ec, unsigned char *data,
+		      unsigned int len);
+static struct rand_data *lrng_jent_state;
+
+u32 lrng_get_jent(u8 *outbuf, unsigned int outbuflen)
+{
+	int ret;
+	u32 ent_bits = jitterrng;
+	unsigned long flags;
+	static DEFINE_SPINLOCK(lrng_jent_lock);
+	static int lrng_jent_initialized = 0;
+
+	spin_lock_irqsave(&lrng_jent_lock, flags);
+
+	if (!ent_bits || (lrng_jent_initialized == -1)) {
+		spin_unlock_irqrestore(&lrng_jent_lock, flags);
+		return 0;
+	}
+
+	if (!lrng_jent_initialized) {
+		lrng_jent_state = jent_lrng_entropy_collector();
+		if (!lrng_jent_state) {
+			jitterrng = 0;
+			lrng_jent_initialized = -1;
+			spin_unlock_irqrestore(&lrng_jent_lock, flags);
+			pr_info("Jitter RNG unusable on current system\n");
+			return 0;
+		}
+		lrng_jent_initialized = 1;
+		pr_debug("Jitter RNG working on current system\n");
+	}
+	ret = jent_read_entropy(lrng_jent_state, outbuf, outbuflen);
+	spin_unlock_irqrestore(&lrng_jent_lock, flags);
+
+	if (ret) {
+		pr_debug("Jitter RNG failed with %d\n", ret);
+		return 0;
+	}
+
+	/* Obtain entropy statement */
+	if (outbuflen != LRNG_DRNG_SECURITY_STRENGTH_BYTES)
+		ent_bits = (ent_bits * outbuflen<<3) /
+			   LRNG_DRNG_SECURITY_STRENGTH_BITS;
+	/* Cap entropy to buffer size in bits */
+	ent_bits = min_t(u32, ent_bits, outbuflen<<3);
+	pr_debug("obtained %u bits of entropy from Jitter RNG noise source\n",
+		 ent_bits);
+
+	return ent_bits;
+}
+
+u32 lrng_jent_entropylevel(void)
+{
+	return min_t(u32, jitterrng, LRNG_DRNG_SECURITY_STRENGTH_BITS);
+}
-- 
2.23.0





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v25 10/12] LRNG - add TRNG support
  2019-11-16  9:32 ` [PATCH v25 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                     ` (8 preceding siblings ...)
  2019-11-16  9:36   ` [PATCH v25 09/12] LRNG - add Jitter RNG fast noise source Stephan Müller
@ 2019-11-16  9:37   ` Stephan Müller
  2019-11-16 16:09     ` Andy Lutomirski
  2019-11-16  9:37   ` [PATCH v25 11/12] LRNG - add SP800-90B compliant health tests Stephan Müller
                     ` (2 subsequent siblings)
  12 siblings, 1 reply; 162+ messages in thread
From: Stephan Müller @ 2019-11-16  9:37 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

The True Random Number Generator (TRNG) provides a random number
generator with prediction resistance (SP800-90A terminology) or an NTG.1
(AIS 31 terminology).

When enabled, it obtains random numbers from the entropy pool and
maintains the information with how much entropy it was seeded with. The
TRNG only generates as much output data as it has as entropy.

The secondary DRNGs seed from the TRNG if it is present. In addition,
the /dev/random device accesses the TRNG.

If the TRNG is disabled, the secondary DRNGs seed from the entropy pool
and /dev/random behaves like getrandom(2).

The TRNG benefits from the switchable DRNG support which implies that
data provided via /dev/random is generated by the loaded DRNG.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Kconfig     |  22 +++
 drivers/char/lrng/Makefile    |   1 +
 drivers/char/lrng/lrng_trng.c | 283 ++++++++++++++++++++++++++++++++++
 3 files changed, 306 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_trng.c

diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
index 80fc723c67d2..122d67ee110e 100644
--- a/drivers/char/lrng/Kconfig
+++ b/drivers/char/lrng/Kconfig
@@ -91,4 +91,26 @@ config LRNG_JENT
 	  time or at runtime with the lrng_base.jitterrng configuration
 	  variable.
 
+config LRNG_TRNG_SUPPORT
+	bool "Enable True Random Number Generator support"
+	default y
+	help
+	  The true random number generator (TRNG) support, also
+	  known as DRNG with prediction resistance (SP800-90A
+	  terminology) or NTG.1 (AIS 31 terminology), generates
+	  random numbers after a successful reseed with entropy.
+	  Only when new entropy is provided for a new generation
+	  request, random data is provided with an equal amount
+	  as entropy was added. The TRNG is available via
+	  /dev/random.
+
+	  If the support is not enabled, /dev/random ensures that
+	  it received sufficient initial entropy and will produce
+	  random data without requiring a constant reseed with
+	  entropy. Yet it tries to regularly reseed itself with
+	  fresh entropy.
+
+	  With the TRNG support the /dev/random device will block
+	  if insufficient entropy is available.
+
 endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index a87d800c9aae..1c72bc060bce 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -14,3 +14,4 @@ obj-$(CONFIG_LRNG_DRNG_SWITCH)	+= lrng_switch.o
 obj-$(CONFIG_LRNG_DRBG)		+= lrng_drbg.o
 obj-$(CONFIG_LRNG_KCAPI)	+= lrng_kcapi.o
 obj-$(CONFIG_LRNG_JENT)		+= lrng_jent.o
+obj-$(CONFIG_LRNG_TRNG_SUPPORT)	+= lrng_trng.o
diff --git a/drivers/char/lrng/lrng_trng.c b/drivers/char/lrng/lrng_trng.c
new file mode 100644
index 000000000000..52ea33342a3f
--- /dev/null
+++ b/drivers/char/lrng/lrng_trng.c
@@ -0,0 +1,283 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG True Random Number Generator (TRNG) processing
+ *
+ * Copyright (C) 2016 - 2019, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/lrng.h>
+
+#include "lrng_internal.h"
+
+/* TRNG state handle */
+struct lrng_trng {
+	void *trng;				/* TRNG handle */
+	void *hash;				/* Hash handle */
+	u32 trng_entropy_bits;			/* TRNG entropy level */
+	const struct lrng_crypto_cb *crypto_cb;	/* Crypto callbacks */
+	struct mutex lock;
+};
+
+/* TRNG for /dev/random and seed source for the secondary DRNG(s) */
+static struct lrng_trng lrng_trng = {
+	.trng		= &primary_chacha20,
+	.crypto_cb	= &lrng_cc20_crypto_cb,
+	.lock		= __MUTEX_INITIALIZER(lrng_trng.lock)
+};
+
+/********************************** Helper ************************************/
+
+void lrng_trng_reset(void)
+{
+	lrng_trng.trng_entropy_bits = 0;
+	pr_debug("reset TRNG\n");
+}
+
+void lrng_trng_init(void)
+{
+	mutex_lock(&lrng_trng.lock);
+	lrng_trng_reset();
+	lrng_cc20_init_state(&primary_chacha20);
+	mutex_unlock(&lrng_trng.lock);
+}
+
+/************************* Random Number Generation ***************************/
+
+/* Caller must hold lrng_trng.lock */
+static int lrng_trng_generate(u8 *outbuf, u32 outbuflen)
+{
+	struct lrng_trng *trng = &lrng_trng;
+	const struct lrng_crypto_cb *crypto_cb = trng->crypto_cb;
+	int ret;
+
+	/*
+	 * Only deliver as many bytes as the DRNG is seeded with except during
+	 * initialization to provide a first seed to the secondary DRNG.
+	 */
+	if (lrng_state_min_seeded())
+		outbuflen = min_t(u32, outbuflen, trng->trng_entropy_bits>>3);
+	else
+		outbuflen = min_t(u32, outbuflen,
+				  LRNG_MIN_SEED_ENTROPY_BITS>>3);
+	if (!outbuflen)
+		return 0;
+
+	ret = crypto_cb->lrng_drng_generate_helper_full(trng->trng, outbuf,
+							outbuflen);
+	if (ret != outbuflen) {
+		pr_warn("getting random data from TRNG failed (%d)\n",
+			ret);
+		return ret;
+	}
+
+	if (trng->trng_entropy_bits > (u32)(ret<<3))
+		trng->trng_entropy_bits -= ret<<3;
+	else
+		trng->trng_entropy_bits = 0;
+	pr_debug("obtained %d bytes of random data from TRNG\n", ret);
+	pr_debug("TRNG entropy level at %u bits\n",
+		 trng->trng_entropy_bits);
+
+	return ret;
+}
+
+/**
+ * Inject data into the TRNG with a given entropy value. The function calls
+ * the DRNG's update function. This function also generates random data if
+ * requested by caller. The caller is only returned the amount of random data
+ * that is at most equal to the amount of entropy that just seeded the DRNG.
+ *
+ * Note, this function seeds the TRNG and generates data in an atomic operation.
+ *
+ * @inbuf: buffer to inject
+ * @inbuflen: length of inbuf
+ * @entropy_bits: entropy value of the data in inbuf in bits
+ * @outbuf: buffer to fill immediately after seeding to get full entropy
+ * @outbuflen: length of outbuf
+ * @return: number of bytes written to outbuf, 0 if outbuf is not supplied,
+ *	    or < 0 in case of error
+ */
+static int lrng_trng_inject(const u8 *inbuf, u32 inbuflen, u32 entropy_bits,
+			    u8 *outbuf, u32 outbuflen)
+{
+	struct lrng_trng *trng = &lrng_trng;
+	int ret;
+
+	/* cap the maximum entropy value to the provided data length */
+	entropy_bits = min_t(u32, entropy_bits, inbuflen<<3);
+
+	mutex_lock(&trng->lock);
+	ret = trng->crypto_cb->lrng_drng_seed_helper(trng->trng, inbuf,
+						      inbuflen);
+	if (ret < 0) {
+		pr_warn("(re)seeding of TRNG failed\n");
+		goto unlock;
+	}
+	pr_debug("inject %u bytes with %u bits of entropy into TRNG\n",
+		 inbuflen, entropy_bits);
+
+	/* Adjust the fill level indicator to at most the DRNG sec strength */
+	trng->trng_entropy_bits =
+		min_t(u32, trng->trng_entropy_bits + entropy_bits,
+		      LRNG_DRNG_SECURITY_STRENGTH_BITS);
+	lrng_init_ops(trng->trng_entropy_bits);
+
+	if (outbuf && outbuflen)
+		ret = lrng_trng_generate(outbuf, outbuflen);
+
+unlock:
+	mutex_unlock(&trng->lock);
+	lrng_reader_wakeup();
+
+	return ret;
+}
+
+/**
+ * Seed the TRNG from the internal noise sources and generate random data. The
+ * seeding and the generation of random data is an atomic operation.
+ *
+ * lrng_pool_trylock() must be invoked successfully by caller.
+ */
+int lrng_trng_seed(u8 *outbuf, u32 outbuflen, bool drain)
+{
+	struct entropy_buf entropy_buf __aligned(LRNG_KCAPI_ALIGN);
+	struct lrng_trng *trng = &lrng_trng;
+	u32 total_entropy_bits;
+	int ret = 0, retrieved = 0;
+
+	/* Get available entropy in primary DRNG */
+	if (trng->trng_entropy_bits>>3) {
+		mutex_lock(&trng->lock);
+		ret = lrng_trng_generate(outbuf, outbuflen);
+		mutex_unlock(&trng->lock);
+		if (ret > 0) {
+			retrieved += ret;
+			if (ret == outbuflen)
+				goto out;
+
+			outbuf += ret;
+			outbuflen -= ret;
+		}
+		/* Disregard error code as another generate request is below. */
+	}
+
+	mutex_lock(&trng->lock);
+	total_entropy_bits = lrng_fill_seed_buffer(trng->crypto_cb, trng->hash,
+						   &entropy_buf, drain);
+	mutex_unlock(&trng->lock);
+
+	pr_debug("reseed TRNG from internal noise sources with %u bits "
+		 "of entropy\n", total_entropy_bits);
+
+	ret = lrng_trng_inject((u8 *)&entropy_buf, sizeof(entropy_buf),
+				total_entropy_bits,
+				outbuf, outbuflen);
+
+	memzero_explicit(&entropy_buf, sizeof(entropy_buf));
+
+	if (ret > 0)
+		retrieved += ret;
+
+out:
+	/* Allow the seeding operation to be called again */
+	lrng_pool_unlock();
+
+	return (ret >= 0) ? retrieved : ret;
+}
+
+/**
+ * Obtain random data from TRNG with information theoretical entropy by
+ * triggering a reseed. The TRNG will only return as many random bytes as it
+ * was seeded with.
+ *
+ * @outbuf: buffer to store the random data in
+ * @outbuflen: length of outbuf
+ * @return: < 0 on error
+ *	    >= 0 the number of bytes that were obtained
+ */
+int lrng_trng_get(u8 *outbuf, u32 outbuflen)
+{
+	int ret;
+
+	if (!outbuf || !outbuflen)
+		return 0;
+
+	lrng_drngs_init_cc20();
+
+	if (lrng_pool_trylock())
+		return -EINPROGRESS;
+	ret = lrng_trng_seed(outbuf, outbuflen, true);
+	if (ret >= 0) {
+		pr_debug("read %d bytes of full entropy data from TRNG\n", ret);
+	} else {
+		/* This is no error, but we have not generated anything */
+		if (ret == -EINPROGRESS)
+			return 0;
+		pr_debug("reading data from TRNG failed: %d\n", ret);
+	}
+
+	return ret;
+}
+
+#ifdef CONFIG_LRNG_DRNG_SWITCH
+int lrng_trng_switch(const struct lrng_crypto_cb *cb)
+{
+	int ret;
+	u8 seed[LRNG_DRNG_SECURITY_STRENGTH_BYTES];
+	void *trng, *hash;
+
+	trng = cb->lrng_drng_alloc(LRNG_DRNG_SECURITY_STRENGTH_BYTES);
+	if (IS_ERR(trng))
+		return PTR_ERR(trng);
+
+	hash = cb->lrng_hash_alloc(seed, sizeof(seed));
+	if (IS_ERR(hash)) {
+		pr_warn("could not allocate new LRNG pool hash (%ld)\n",
+			PTR_ERR(hash));
+		cb->lrng_drng_dealloc(trng);
+		return PTR_ERR(hash);
+	}
+
+	/* Update primary DRNG */
+	mutex_lock(&lrng_trng.lock);
+	/* pull from existing DRNG to seed new DRNG */
+	ret = lrng_trng.crypto_cb->lrng_drng_generate_helper_full(
+					lrng_trng.trng, seed, sizeof(seed));
+	if (ret < 0) {
+		lrng_trng_reset();
+		pr_warn("getting random data from TRNG failed (%d)\n", ret);
+	} else {
+		/*
+		 * No change of the seed status as the old and new DRNG have
+		 * same security strength.
+		 */
+		ret = cb->lrng_drng_seed_helper(trng, seed, ret);
+		if (ret < 0) {
+			lrng_trng_reset();
+			pr_warn("seeding of new TRNG failed (%d)\n", ret);
+		} else {
+			pr_debug("seeded new TRNG instance from old TRNG "
+				 "instance\n");
+		}
+	}
+	memzero_explicit(seed, sizeof(seed));
+
+	if (!lrng_get_available())
+		lrng_trng_reset();
+	lrng_trng.crypto_cb->lrng_drng_dealloc(lrng_trng.trng);
+	lrng_trng.trng = trng;
+
+	lrng_trng.crypto_cb->lrng_hash_dealloc(lrng_trng.hash);
+	lrng_trng.hash = hash;
+
+	lrng_trng.crypto_cb = cb;
+
+	mutex_unlock(&lrng_trng.lock);
+
+	pr_info("TRNG allocated\n");
+
+	return ret;
+}
+#endif	/* CONFIG_LRNG_DRNG_SWITCH */
-- 
2.23.0





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v25 11/12] LRNG - add SP800-90B compliant health tests
  2019-11-16  9:32 ` [PATCH v25 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                     ` (9 preceding siblings ...)
  2019-11-16  9:37   ` [PATCH v25 10/12] LRNG - add TRNG support Stephan Müller
@ 2019-11-16  9:37   ` Stephan Müller
  2019-11-16  9:38   ` [PATCH v25 12/12] LRNG - add interface for gathering of raw entropy Stephan Müller
  2019-11-23 20:08   ` [PATCH v26 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
  12 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-16  9:37 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

Implement health tests for LRNG's slow noise sources as mandated by
SP-800-90B The file contains the following health tests:

- stuck test: The stuck test calculates the first, second and third
  discrete derivative of the time stamp to be processed by the LFSR.
  Only if all three values are non-zero, the received time delta is
  considered to be non-stuck.

- SP800-90B Repetition Count Test (RCT): The LRNG uses an enhanced
  version of the RCT specified in SP800-90B section 4.4.1. Instead of
  counting identical back-to-back values, the input to the RCT is the
  counting of the stuck values during the processing of received
  interrupt events. The RCT is applied with alpha=2^-30 compliant to
  the recommendation of FIPS 140-2 IG 9.8. During the counting operation,
  the LRNG always calculates the RCT cut-off value of C. If that value
  exceeds the allowed cut-off value, the LRNG will trigger the health
  test failure discussed below. An error is logged to the kernel log
  that such RCT failure occurred. This test is only applied and
  enforced in FIPS mode, i.e. when the kernel compiled with
  CONFIG_CONFIG_FIPS is started with fips=1.

- SP800-90B Adaptive Proportion Test (APT): The LRNG implements the
  APT as defined in SP800-90B section 4.4.2. The applied significance
  level again is alpha=2^-30 compliant to the recommendation of FIPS
  140-2 IG 9.8.

The aforementioned health tests are applied to the first 1,024 time stamps
obtained from interrupt events. In case one error is identified for either
the RCT, or the APT, the collected entropy is invalidated and the
SP800-90B startup health test is restarted.

As long as the SP800-90B startup health test is not completed, all LRNG
random number output interfaces that may block will block and not generate
any data. This implies that only those potentially blocking interfaces are
defined to provide random numbers that are seeded with the interrupt noise
source being SP800-90B compliant. All other output interfaces will not be
affected by the SP800-90B startup test and thus are not considered
SP800-90B compliant.

At runtime, the SP800-90B APT and RCT are applied to each time stamp
generated for a received interrupt. When either the APT and RCT indicates
a noise source failure, the LRNG is reset to a state it has immediately
after boot:

- all entropy counters are set to zero

- the SP800-90B startup tests are re-performed which implies that
getrandom(2) would block again until new entropy was collected

To summarize, the following rules apply:

• SP800-90B compliant output interfaces

  - /dev/random

  - getrandom(2) system call

  -  get_random_bytes kernel-internal interface when being triggered by
     the callback registered with add_random_ready_callback

• SP800-90B non-compliant output interfaces

  - /dev/urandom

  - get_random_bytes kernel-internal interface called directly

  - randomize_page kernel-internal interface

  - get_random_u32 and get_random_u64 kernel-internal interfaces

  - get_random_u32_wait, get_random_u64_wait, get_random_int_wait, and
    get_random_long_wait kernel-internal interfaces

If either the RCT, or the APT health test fails irrespective whether
during initialization or runtime, the following actions occur:

  1. The entropy of the entire entropy pool is invalidated.

  2. The primary and all secondary DRNGs are reset which imply that they
     are treated as being not seeded and require a reseed during next
     invocation.

  3. The SP800-90B startup health test are initiated with all
     implications of the startup tests. That implies that from that point
     on, new events must be observed and its entropy must be inserted into
     the entropy pool before random numbers are calculated from the
     entropy pool.

Further details on the SP800-90B compliance and the availability of all
test tools required to perform all tests mandated by SP800-90B are
provided at [1].

The entire health testing code is compile-time configurable.

The patch provides a CONFIG_BROKEN configuration of the APT / RCT cutoff
values which have a high likelihood to trigger the health test failure.
The BROKEN APT cutoff is set to the exact mean of the expected value if
the time stamps are equally distributed (512 time stamps divided by 16
possible values due to using the 4 LSB of the time stamp). The BROKEN
RCT cutoff value is set to 1 which is likely to be triggered during
regular operation.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Kconfig       |  56 +++++
 drivers/char/lrng/Makefile      |   1 +
 drivers/char/lrng/lrng_health.c | 409 ++++++++++++++++++++++++++++++++
 3 files changed, 466 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_health.c

diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
index 122d67ee110e..e6ca3acc1e48 100644
--- a/drivers/char/lrng/Kconfig
+++ b/drivers/char/lrng/Kconfig
@@ -113,4 +113,60 @@ config LRNG_TRNG_SUPPORT
 	  With the TRNG support the /dev/random device will block
 	  if insufficient entropy is available.
 
+config LRNG_HEALTH_TESTS
+	bool "Enable noise source online health tests"
+	help
+	  The online health tests validate the noise source at
+	  runtime for fatal errors. These tests include SP800-90B
+	  compliant tests which are invoked if the system is booted
+	  with fips=1. In case of fatal errors during active
+	  SP800-90B tests, the issue is logged and the noise
+	  data is discarded. These tests are required for full
+	  compliance with SP800-90B.
+
+	  If unsure, say Y.
+
+config LRNG_RCT_BROKEN
+	bool "SP800-90B RCT with dangerous low cutoff value"
+	depends on LRNG_HEALTH_TESTS
+	depends on BROKEN
+	default n
+	help
+	  This option enables a dangerously low SP800-90B repetitive
+	  count test (RCT) cutoff value which makes it very likely
+	  that the RCT is triggered to raise a self test failure.
+
+	  This option is ONLY intended for developers wanting to
+	  test the effectiveness of the SP800-90B RCT health test.
+
+	  If unsure, say N.
+
+config LRNG_APT_BROKEN
+	bool "SP800-90B APT with dangerous low cutoff value"
+	depends on LRNG_HEALTH_TESTS
+	depends on BROKEN
+	default n
+	help
+	  This option enables a dangerously low SP800-90B adaptive
+	  proportion test (APT) cutoff value which makes it very
+	  likely that the RCT is triggered to raise a self test
+	  failure.
+
+	  This option is ONLY intended for developers wanting to
+	  test the effectiveness of the SP800-90B APT health test.
+
+	  If unsure, say N.
+
+# Default taken from SP800-90B sec 4.4.1 - significance level 2^-30
+config LRNG_RCT_CUTOFF
+	int
+	default 30 if !LRNG_RCT_BROKEN
+	default 1 if LRNG_RCT_BROKEN
+
+# Default taken from SP800-90B sec 4.4.2 - significance level 2^-30
+config LRNG_APT_CUTOFF
+	int
+	default 325 if !LRNG_APT_BROKEN
+	default 32 if LRNG_APT_BROKEN
+
 endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index 1c72bc060bce..0713e9c0aa6e 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -15,3 +15,4 @@ obj-$(CONFIG_LRNG_DRBG)		+= lrng_drbg.o
 obj-$(CONFIG_LRNG_KCAPI)	+= lrng_kcapi.o
 obj-$(CONFIG_LRNG_JENT)		+= lrng_jent.o
 obj-$(CONFIG_LRNG_TRNG_SUPPORT)	+= lrng_trng.o
+obj-$(CONFIG_LRNG_HEALTH_TESTS)	+= lrng_health.o
diff --git a/drivers/char/lrng/lrng_health.c b/drivers/char/lrng/lrng_health.c
new file mode 100644
index 000000000000..9ea34322e0ae
--- /dev/null
+++ b/drivers/char/lrng/lrng_health.c
@@ -0,0 +1,409 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * Linux Random Number Generator (LRNG) Health Testing
+ *
+ * Copyright (C) 2019, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/fips.h>
+#include <linux/module.h>
+
+#include "lrng_internal.h"
+
+/* Stuck Test */
+struct lrng_stuck_test {
+	u32 last_time;		/* Stuck test: time of previous IRQ */
+	u32 last_delta;		/* Stuck test: delta of previous IRQ */
+	u32 last_delta2;	/* Stuck test: 2. time derivation of prev IRQ */
+};
+
+/* Repetition Count Test */
+struct lrng_rct {
+	atomic_t rct_count;	/* Number of stuck values */
+};
+
+/* Adaptive Proportion Test */
+struct lrng_apt {
+	/* Data window size */
+#define LRNG_APT_WINDOW_SIZE	512
+	/* LSB of time stamp to process */
+#define LRNG_APT_LSB		16
+#define LRNG_APT_WORD_MASK	(LRNG_APT_LSB - 1)
+	atomic_t apt_count;		/* APT counter */
+	atomic_t apt_base;		/* APT base reference */
+
+	atomic_t apt_trigger;
+	bool apt_base_set;	/* Is APT base set? */
+};
+
+/* The health test code must operate lock-less */
+struct lrng_health {
+	struct lrng_rct rct;
+	struct lrng_apt apt;
+
+	bool health_test_enabled;
+
+	/* SP800-90B startup health tests */
+#define LRNG_SP80090B_STARTUP_SAMPLES  1024
+#define LRNG_SP80090B_STARTUP_BLOCKS   ((LRNG_SP80090B_STARTUP_SAMPLES + \
+					 LRNG_APT_WINDOW_SIZE - 1) /    \
+					LRNG_APT_WINDOW_SIZE)
+	bool sp80090b_startup_done;
+	atomic_t sp80090b_startup_blocks;
+};
+
+static struct lrng_health lrng_health = {
+	.rct.rct_count = ATOMIC_INIT(0),
+
+	.apt.apt_count = ATOMIC_INIT(0),
+	.apt.apt_base = ATOMIC_INIT(-1),
+	.apt.apt_trigger = ATOMIC_INIT(LRNG_APT_WINDOW_SIZE),
+	.apt.apt_base_set = false,
+
+	.health_test_enabled = true,
+
+	.sp80090b_startup_blocks = ATOMIC_INIT(LRNG_SP80090B_STARTUP_BLOCKS),
+	.sp80090b_startup_done = false,
+};
+
+static DEFINE_PER_CPU(struct lrng_stuck_test, lrng_stuck_test);
+
+static inline bool lrng_sp80090b_health_requested(void)
+{
+	/* Health tests are only requested in FIPS mode */
+	return fips_enabled;
+}
+
+static inline bool lrng_sp80090b_health_enabled(void)
+{
+	struct lrng_health *health = &lrng_health;
+
+	return lrng_sp80090b_health_requested() && health->health_test_enabled;
+}
+
+/***************************************************************************
+ * SP800-90B Compliance
+ *
+ * If the Linux-RNG is booted into FIPS mode, the following interfaces
+ * provide an SP800-90B compliant noise source:
+ *
+ * * /dev/random
+ * * getrandom(2)
+ * * get_random_bytes when using it in conjunction with
+ *   add_random_ready_callback
+ *
+ * All other interfaces, including /dev/urandom or get_random_bytes without
+ * the add_random_ready_callback cannot claim to use an SP800-90B compliant
+ * noise source.
+ ***************************************************************************/
+
+/**
+ * Perform SP800-90B startup testing
+ */
+static inline void lrng_sp80090b_startup(struct lrng_health *health)
+{
+	if (!health->sp80090b_startup_done &&
+	    atomic_dec_and_test(&health->sp80090b_startup_blocks)) {
+		health->sp80090b_startup_done = true;
+		pr_info("SP800-90B startup health tests completed\n");
+		lrng_init_ops(0);
+
+		/*
+		 * Force a reseed of secondary DRNGs to ensure they are
+		 * seeded with entropy that passed the SP800-90B health tests.
+		 * As the primary DRNG always will reseed before generating
+		 * random numbers, it does not need a reseed trigger.
+		 */
+		lrng_sdrng_force_reseed();
+	}
+}
+
+/**
+ * Handle failure of SP800-90B startup testing
+ */
+static inline void lrng_sp80090b_startup_failure(struct lrng_health *health)
+{
+	/* Reset of LRNG and its entropy - NOTE: we are in atomic context */
+	lrng_reset();
+
+	/*
+	 * Reset the SP800-90B startup test.
+	 *
+	 * NOTE SP800-90B section 4.3 bullet 4 does not specify what
+	 * exactly is to be done in case of failure! Thus, we do what
+	 * makes sense, i.e. restarting the health test and thus gating
+	 * the output function of /dev/random and getrandom(2).
+	 */
+	atomic_set(&health->sp80090b_startup_blocks,
+		   LRNG_SP80090B_STARTUP_BLOCKS);
+}
+
+/**
+ * Handle failure of SP800-90B runtime testing
+ */
+static inline void lrng_sp80090b_runtime_failure(struct lrng_health *health)
+{
+	lrng_sp80090b_startup_failure(health);
+	health->sp80090b_startup_done = false;
+}
+
+static inline void lrng_sp80090b_failure(struct lrng_health *health)
+{
+	if (health->sp80090b_startup_done) {
+		pr_err("SP800-90B runtime health test failure - invalidating "
+		       "all existing entropy and initiate SP800-90B startup\n");
+		lrng_sp80090b_runtime_failure(health);
+	} else {
+		pr_err("SP800-90B startup test failure - resetting\n");
+		lrng_sp80090b_startup_failure(health);
+	}
+}
+
+/**
+ * Is the SP800-90B startup testing complete?
+ *
+ * This function is called by the LRNG to determine whether to unblock
+ * a certain user interface. Therefore, only the potentially blocking
+ * user interfaces are considered SP800-90B compliant.
+ */
+bool lrng_sp80090b_startup_complete(void)
+{
+	struct lrng_health *health = &lrng_health;
+
+	return (lrng_sp80090b_health_enabled()) ? health->sp80090b_startup_done:
+						  true;
+}
+
+bool lrng_sp80090b_compliant(void)
+{
+	struct lrng_health *health = &lrng_health;
+
+	return lrng_sp80090b_health_enabled() && health->sp80090b_startup_done;
+}
+
+/***************************************************************************
+ * Adaptive Proportion Test
+ *
+ * This test complies with SP800-90B section 4.4.2.
+ ***************************************************************************/
+
+/**
+ * Reset the APT counter
+ *
+ * @health [in] Reference to health state
+ */
+static inline void lrng_apt_reset(struct lrng_health *health,
+				  unsigned int time_masked)
+{
+	struct lrng_apt *apt = &health->apt;
+
+	pr_debug("APT value %d for base %d\n",
+		 atomic_read(&apt->apt_count), atomic_read(&apt->apt_base));
+
+	/* Reset APT */
+	atomic_set(&apt->apt_count, 0);
+	atomic_set(&apt->apt_base, time_masked);
+}
+
+static inline void lrng_apt_restart(struct lrng_health *health)
+{
+	struct lrng_apt *apt = &health->apt;
+
+	atomic_set(&apt->apt_trigger, LRNG_APT_WINDOW_SIZE);
+}
+
+/**
+ * Insert a new entropy event into APT
+ *
+ * This function does is void as it does not decide about the fate of a time
+ * stamp. An APT failure can only happen at the same time of a stuck test
+ * failure. Thus, the stuck failure will already decide how the time stamp
+ * is handled.
+ *
+ * @health [in] Reference to health state
+ * @now_time [in] Time stamp to process
+ */
+static inline void lrng_apt_insert(struct lrng_health *health,
+				   unsigned int now_time)
+{
+	struct lrng_apt *apt = &health->apt;
+
+	if (!lrng_sp80090b_health_requested())
+		return;
+
+	now_time &= LRNG_APT_WORD_MASK;
+
+	/* Initialization of APT */
+	if (!apt->apt_base_set) {
+		atomic_set(&apt->apt_base, now_time);
+		apt->apt_base_set = true;
+		return;
+	}
+
+	if (now_time == (unsigned int)atomic_read(&apt->apt_base)) {
+		u32 apt_val = (u32)atomic_inc_return_relaxed(&apt->apt_count);
+
+		if (apt_val >= CONFIG_LRNG_APT_CUTOFF)
+			lrng_sp80090b_failure(health);
+	}
+
+	if (atomic_dec_and_test(&apt->apt_trigger)) {
+		lrng_apt_restart(health);
+		lrng_apt_reset(health, now_time);
+		lrng_sp80090b_startup(health);
+	}
+}
+
+/***************************************************************************
+ * Repetition Count Test
+ *
+ * The LRNG uses an enhanced version of the Repetition Count Test
+ * (RCT) specified in SP800-90B section 4.4.1. Instead of counting identical
+ * back-to-back values, the input to the RCT is the counting of the stuck
+ * values while filling the entropy pool.
+ *
+ * The RCT is applied with an alpha of 2^-30 compliant to FIPS 140-2 IG 9.8.
+ *
+ * During the counting operation, the LRNG always calculates the RCT
+ * cut-off value of C. If that value exceeds the allowed cut-off value,
+ * the LRNG will invalidate all entropy for the entropy pool which implies
+ * that no data can be extracted from the entropy pool unless new entropy
+ * is received.
+ ***************************************************************************/
+
+/**
+ * Hot code path - Insert data for Repetition Count Test
+ *
+ * @health: Reference to health information
+ * @stuck: Decision of stuck test
+ */
+static inline void lrng_rct(struct lrng_health *health, int stuck)
+{
+	struct lrng_rct *rct = &health->rct;
+
+	if (!lrng_sp80090b_health_requested())
+		return;
+
+	if (stuck) {
+		u32 rct_count = atomic_add_return_relaxed(1, &rct->rct_count);
+
+		pr_debug("RCT count: %u\n", rct_count);
+
+		/*
+		 * The cutoff value is based on the following consideration:
+		 * alpha = 2^-30 as recommended in FIPS 140-2 IG 9.8.
+		 * In addition, we imply an entropy value H of 1 bit as this
+		 * is the minimum entropy required to provide full entropy.
+		 *
+		 * Note, rct_count (which equals to value B in the
+		 * pseudo code of SP800-90B section 4.4.1) starts with zero.
+		 * Hence we need to subtract one from the cutoff value as
+		 * calculated following SP800-90B.
+		 */
+		if (rct_count >= CONFIG_LRNG_RCT_CUTOFF) {
+			atomic_set(&rct->rct_count, 0);
+
+			/*
+			 * APT must start anew as we consider all previously
+			 * recorded data to contain no entropy.
+			 */
+			lrng_apt_restart(health);
+
+			lrng_sp80090b_failure(health);
+		}
+	} else {
+		atomic_set(&rct->rct_count, 0);
+	}
+}
+
+/***************************************************************************
+ * Stuck Test
+ *
+ * Checking the:
+ *      1st derivative of the event occurrence (time delta)
+ *      2nd derivative of the event occurrence (delta of time deltas)
+ *      3rd derivative of the event occurrence (delta of delta of time deltas)
+ *
+ * All values must always be non-zero. The stuck test is only valid disabled if
+ * high-resolution time stamps are identified after initialization.
+ ***************************************************************************/
+
+static inline u32 lrng_delta(u32 prev, u32 next)
+{
+	/*
+	 * Note that this (unsigned) subtraction does yield the correct value
+	 * in the wraparound-case, i.e. when next < prev.
+	 */
+	return (next - prev);
+}
+
+/**
+ * Hot code path
+ *
+ * @health: Reference to health information
+ * @now: Event time
+ * @return: 0 event occurrence not stuck (good time stamp)
+ *	    != 0 event occurrence stuck (reject time stamp)
+ */
+static inline int lrng_irq_stuck(struct lrng_stuck_test *stuck, u32 now_time)
+{
+	u32 delta = lrng_delta(stuck->last_time, now_time);
+	u32 delta2 = lrng_delta(stuck->last_delta, delta);
+	u32 delta3 = lrng_delta(stuck->last_delta2, delta2);
+
+	stuck->last_time = now_time;
+	stuck->last_delta = delta;
+	stuck->last_delta2 = delta2;
+
+	if (!delta || !delta2 || !delta3)
+		return 1;
+
+	return 0;
+}
+
+/***************************************************************************
+ * Health test interfaces
+ ***************************************************************************/
+
+/**
+ * Disable all health tests
+ */
+void lrng_health_disable(void)
+{
+	struct lrng_health *health = &lrng_health;
+
+	health->health_test_enabled = false;
+
+	if (lrng_sp80090b_health_requested())
+		pr_warn("SP800-90B compliance requested but the Linux RNG is "
+			"NOT SP800-90B compliant\n");
+}
+
+/**
+ * Hot code path - Perform health test on time stamp received from an event
+ *
+ * @now_time Time stap
+ */
+enum lrng_health_res lrng_health_test(u32 now_time)
+{
+	struct lrng_health *health = &lrng_health;
+	struct lrng_stuck_test *stuck_test = this_cpu_ptr(&lrng_stuck_test);
+	int stuck;
+
+	if (!health->health_test_enabled)
+		return lrng_health_pass;
+
+	lrng_apt_insert(health, now_time);
+
+	stuck = lrng_irq_stuck(stuck_test, now_time);
+	lrng_rct(health, stuck);
+	if (stuck) {
+		/* SP800-90B disallows using a failing health test time stamp */
+		return lrng_sp80090b_health_requested() ?
+			lrng_health_fail_drop : lrng_health_fail_use;
+	}
+
+	return lrng_health_pass;
+}
-- 
2.23.0





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v25 12/12] LRNG - add interface for gathering of raw entropy
  2019-11-16  9:32 ` [PATCH v25 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                     ` (10 preceding siblings ...)
  2019-11-16  9:37   ` [PATCH v25 11/12] LRNG - add SP800-90B compliant health tests Stephan Müller
@ 2019-11-16  9:38   ` Stephan Müller
  2019-11-16 16:51     ` Andy Lutomirski
                       ` (2 more replies)
  2019-11-23 20:08   ` [PATCH v26 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
  12 siblings, 3 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-16  9:38 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

The test interface allows a privileged process to capture the raw
unconditioned noise that is collected by the LRNG for statistical
analysis. Extracted noise data is not used to seed the LRNG. This
is a test interface and not appropriate for production systems.
Yet, the interface is considered to be sufficiently secured for
production systems.

Access to the data is given through the lrng_raw debugfs file. The
data buffer should be multiples of sizeof(u32) to fill the entire
buffer. Using the option lrng_testing.boot_test=1 the raw noise of
the first 1000 entropy events since boot can be sampled.

This test interface allows generating the data required for
analysis whether the LRNG is in compliance with SP800-90B
sections 3.1.3 and 3.1.4.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Kconfig        |  16 ++
 drivers/char/lrng/Makefile       |   1 +
 drivers/char/lrng/lrng_testing.c | 324 +++++++++++++++++++++++++++++++
 3 files changed, 341 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_testing.c

diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
index e6ca3acc1e48..4ccc710832ef 100644
--- a/drivers/char/lrng/Kconfig
+++ b/drivers/char/lrng/Kconfig
@@ -169,4 +169,20 @@ config LRNG_APT_CUTOFF
 	default 325 if !LRNG_APT_BROKEN
 	default 32 if LRNG_APT_BROKEN
 
+config LRNG_TESTING
+	bool "Enable entropy test interface to LRNG noise source"
+	select CONFIG_DEBUG_FS
+	help
+	  The test interface allows a privileged process to capture
+	  the raw unconditioned noise that is collected by the LRNG
+	  for statistical analysis. Extracted noise data is not used
+	  to seed the LRNG.
+
+	  The raw noise data can be obtained using the lrng_raw
+	  debugfs file. Using the option lrng_testing.boot_test=1
+	  the raw noise of the first 1000 entropy events since boot
+	  can be sampled.
+
+	  If unsure, say N.
+
 endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index 0713e9c0aa6e..c0b6cc4301fe 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -16,3 +16,4 @@ obj-$(CONFIG_LRNG_KCAPI)	+= lrng_kcapi.o
 obj-$(CONFIG_LRNG_JENT)		+= lrng_jent.o
 obj-$(CONFIG_LRNG_TRNG_SUPPORT)	+= lrng_trng.o
 obj-$(CONFIG_LRNG_HEALTH_TESTS)	+= lrng_health.o
+obj-$(CONFIG_LRNG_TESTING)	+= lrng_testing.o
diff --git a/drivers/char/lrng/lrng_testing.c b/drivers/char/lrng/lrng_testing.c
new file mode 100644
index 000000000000..5c33d3bd2172
--- /dev/null
+++ b/drivers/char/lrng/lrng_testing.c
@@ -0,0 +1,324 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * Linux Random Number Generator (LRNG) Raw entropy collection tool
+ *
+ * Copyright (C) 2019, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/atomic.h>
+#include <linux/bug.h>
+#include <linux/debugfs.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/sched/signal.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+#include <linux/workqueue.h>
+#include <asm/errno.h>
+
+#include "lrng_internal.h"
+
+#define LRNG_TESTING_RINGBUFFER_SIZE	1024
+#define LRNG_TESTING_RINGBUFFER_MASK	(LRNG_TESTING_RINGBUFFER_SIZE - 1)
+
+static u32 lrng_testing_rb[LRNG_TESTING_RINGBUFFER_SIZE];
+static atomic_t lrng_rb_reader = ATOMIC_INIT(0);
+static atomic_t lrng_rb_writer = ATOMIC_INIT(0);
+static atomic_t lrng_rb_first_in = ATOMIC_INIT(0);
+static atomic_t lrng_testing_enabled = ATOMIC_INIT(0);
+
+static DECLARE_WAIT_QUEUE_HEAD(lrng_raw_read_wait);
+
+static u32 boot_test = 0;
+module_param(boot_test, uint, 0644);
+MODULE_PARM_DESC(boot_test, "Enable gathering boot time entropy of the first"
+			    " entropy events");
+
+static inline void lrng_raw_entropy_reset(void)
+{
+	atomic_set(&lrng_rb_reader, 0);
+	atomic_set(&lrng_rb_writer, 0);
+	atomic_set(&lrng_rb_first_in, 0);
+}
+
+static void lrng_raw_entropy_init(void)
+{
+	/*
+	 * The boot time testing implies we have a running test. If the
+	 * caller wants to clear it, he has to unset the boot_test flag
+	 * at runtime via sysfs to enable regular runtime testing
+	 */
+	if (boot_test)
+		return;
+
+	lrng_raw_entropy_reset();
+	atomic_set(&lrng_testing_enabled, 1);
+	pr_warn("Enabling raw entropy collection\n");
+}
+
+static void lrng_raw_entropy_fini(void)
+{
+	if (boot_test)
+		return;
+
+	lrng_raw_entropy_reset();
+	atomic_set(&lrng_testing_enabled, 0);
+	pr_warn("Disabling raw entropy collection\n");
+}
+
+bool lrng_raw_entropy_store(u32 value)
+{
+	unsigned int write_ptr;
+	unsigned int read_ptr;
+
+	if (!atomic_read(&lrng_testing_enabled) && !boot_test)
+		return false;
+
+	write_ptr = (unsigned int)atomic_add_return_relaxed(1, &lrng_rb_writer);
+	read_ptr = (unsigned int)atomic_read(&lrng_rb_reader);
+
+	/*
+	 * Disable entropy testing for boot time testing after ring buffer
+	 * is filled.
+	 */
+	if (boot_test && write_ptr > LRNG_TESTING_RINGBUFFER_SIZE) {
+		pr_warn_once("Boot time entropy collection test disabled\n");
+		return false;
+	}
+
+	if (boot_test && !atomic_read(&lrng_rb_first_in))
+		pr_warn("Boot time entropy collection test enabled\n");
+
+	lrng_testing_rb[write_ptr & LRNG_TESTING_RINGBUFFER_MASK] = value;
+
+	/* We got at least one event, enable the reader now. */
+	atomic_set(&lrng_rb_first_in, 1);
+
+	if (wq_has_sleeper(&lrng_raw_read_wait))
+		wake_up_interruptible(&lrng_raw_read_wait);
+
+	/*
+	 * Our writer is taking over the reader - this means the reader
+	 * one full ring buffer available. Thus we "push" the reader ahead
+	 * to guarantee that he will be able to consume the full ring.
+	 */
+	if (!boot_test &&
+	    ((write_ptr & LRNG_TESTING_RINGBUFFER_MASK) ==
+	    (read_ptr & LRNG_TESTING_RINGBUFFER_MASK)))
+		atomic_inc_return_relaxed(&lrng_rb_reader);
+
+	return true;
+}
+
+static inline bool lrng_raw_have_data(void)
+{
+	unsigned int read_ptr = (unsigned int)atomic_read(&lrng_rb_reader);
+	unsigned int write_ptr = (unsigned int)atomic_read(&lrng_rb_writer);
+
+	return (atomic_read(&lrng_rb_first_in) &&
+		(write_ptr & LRNG_TESTING_RINGBUFFER_MASK) !=
+		 (read_ptr & LRNG_TESTING_RINGBUFFER_MASK));
+}
+
+static int lrng_raw_entropy_reader(u8 *outbuf, u32 outbuflen)
+{
+	int collected_data = 0;
+
+	if (!atomic_read(&lrng_testing_enabled) && !boot_test)
+		return -EAGAIN;
+
+	if (!atomic_read(&lrng_rb_first_in)) {
+		wait_event_interruptible(lrng_raw_read_wait,
+					 lrng_raw_have_data());
+		if (signal_pending(current))
+			return -ERESTARTSYS;
+	}
+
+	while (outbuflen) {
+		unsigned int read_ptr =
+			(unsigned int)atomic_add_return_relaxed(
+							1, &lrng_rb_reader);
+		unsigned int write_ptr =
+			(unsigned int)atomic_read(&lrng_rb_writer);
+
+		/*
+		 * For boot time testing, only output one round of ring buffer.
+		 */
+		if (boot_test && read_ptr > LRNG_TESTING_RINGBUFFER_SIZE) {
+			collected_data = -ENOMSG;
+			goto out;
+		}
+
+		/* We reached the writer */
+		if (!boot_test && ((write_ptr & LRNG_TESTING_RINGBUFFER_MASK) ==
+		    (read_ptr & LRNG_TESTING_RINGBUFFER_MASK))) {
+			wait_event_interruptible(lrng_raw_read_wait,
+						 lrng_raw_have_data());
+			if (signal_pending(current))
+				return -ERESTARTSYS;
+
+			continue;
+		}
+
+		/* We copy out word-wise */
+		if (outbuflen < sizeof(u32)) {
+			atomic_dec_return_relaxed(&lrng_rb_reader);
+			goto out;
+		}
+
+		memcpy(outbuf,
+		       &lrng_testing_rb[read_ptr & LRNG_TESTING_RINGBUFFER_MASK],
+		       sizeof(u32));
+		outbuf += sizeof(u32);
+		outbuflen -= sizeof(u32);
+		collected_data += sizeof(u32);
+	}
+
+out:
+	return collected_data;
+}
+
+/**************************************************************************
+ * Debugfs interface
+ **************************************************************************/
+static int lrng_raw_extract_user(char __user *buf, size_t nbytes)
+{
+	u8 *tmp, *tmp_aligned;
+	int ret = 0, large_request = (nbytes > 256);
+
+	/*
+	 * The intention of this interface is for collecting at least
+	 * 1000 samples due to the SP800-90B requirements. So, we make no
+	 * effort in avoiding allocating more memory that actually needed
+	 * by the user. Hence, we allocate sufficient memory to always hold
+	 * that amount of data.
+	 */
+	tmp = kmalloc(LRNG_TESTING_RINGBUFFER_SIZE + sizeof(u32), GFP_KERNEL);
+	if (!tmp)
+		return -ENOMEM;
+
+	tmp_aligned = PTR_ALIGN(tmp, sizeof(u32));
+
+	while (nbytes) {
+		int i;
+
+		if (large_request && need_resched()) {
+			if (signal_pending(current)) {
+				if (ret == 0)
+					ret = -ERESTARTSYS;
+				break;
+			}
+			schedule();
+		}
+
+		i = min_t(int, nbytes, LRNG_TESTING_RINGBUFFER_SIZE);
+		i = lrng_raw_entropy_reader(tmp_aligned, i);
+		if (i <= 0) {
+			if (i < 0)
+				ret = i;
+			break;
+		}
+		if (copy_to_user(buf, tmp_aligned, i)) {
+			ret = -EFAULT;
+			break;
+		}
+
+		nbytes -= i;
+		buf += i;
+		ret += i;
+	}
+
+	kzfree(tmp);
+	return ret;
+}
+
+/*
+ * This data structure holds the dentry's of the debugfs files establishing
+ * the interface to user space.
+ */
+struct lrng_raw_debugfs {
+	struct dentry *lrng_raw_debugfs_root; /* root dentry */
+	struct dentry *lrng_raw_debugfs_lrng_raw; /* .../lrng_raw */
+};
+
+static struct lrng_raw_debugfs lrng_raw_debugfs;
+
+/* DebugFS operations and definition of the debugfs files */
+static ssize_t lrng_raw_read(struct file *file, char __user *to,
+			     size_t count, loff_t *ppos)
+{
+	loff_t pos = *ppos;
+	int ret;
+
+	if (!count)
+		return 0;
+	lrng_raw_entropy_init();
+	ret = lrng_raw_extract_user(to, count);
+	lrng_raw_entropy_fini();
+	if (ret < 0)
+		return ret;
+	count -= ret;
+	*ppos = pos + count;
+	return ret;
+}
+
+/* Module init: allocate memory, register the debugfs files */
+static int lrng_raw_debugfs_init(void)
+{
+	lrng_raw_debugfs.lrng_raw_debugfs_root =
+		debugfs_create_dir(KBUILD_MODNAME, NULL);
+	if (IS_ERR(lrng_raw_debugfs.lrng_raw_debugfs_root)) {
+		lrng_raw_debugfs.lrng_raw_debugfs_root = NULL;
+		return PTR_ERR(lrng_raw_debugfs.lrng_raw_debugfs_root);
+	}
+	return 0;
+}
+
+static struct file_operations lrng_raw_name_fops = {
+	.owner = THIS_MODULE,
+	.read = lrng_raw_read,
+};
+
+static int lrng_raw_debugfs_init_name(void)
+{
+	lrng_raw_debugfs.lrng_raw_debugfs_lrng_raw =
+		debugfs_create_file("lrng_raw", 0400,
+				    lrng_raw_debugfs.lrng_raw_debugfs_root,
+				    NULL, &lrng_raw_name_fops);
+	if (IS_ERR(lrng_raw_debugfs.lrng_raw_debugfs_lrng_raw)) {
+		lrng_raw_debugfs.lrng_raw_debugfs_lrng_raw = NULL;
+		return PTR_ERR(lrng_raw_debugfs.lrng_raw_debugfs_lrng_raw);
+	}
+	return 0;
+}
+
+static int __init lrng_raw_init(void)
+{
+	int ret = lrng_raw_debugfs_init();
+
+	if (ret < 0)
+		return ret;
+
+	ret = lrng_raw_debugfs_init_name();
+	if (ret < 0)
+		debugfs_remove_recursive(
+					lrng_raw_debugfs.lrng_raw_debugfs_root);
+
+	return ret;
+}
+
+static void __exit lrng_raw_exit(void)
+{
+	debugfs_remove_recursive(lrng_raw_debugfs.lrng_raw_debugfs_root);
+}
+
+module_init(lrng_raw_init);
+module_exit(lrng_raw_exit);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
+MODULE_DESCRIPTION("Kernel module for gathering raw entropy");
-- 
2.23.0





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* Re: [PATCH v25 01/12] Linux Random Number Generator
  2019-11-16  9:33   ` [PATCH v25 01/12] Linux Random Number Generator Stephan Müller
@ 2019-11-16 11:25     ` Thomas Gleixner
  2019-11-17 10:30       ` Stephan Müller
  2019-11-16 18:13     ` Nicolai Stange
  1 sibling, 1 reply; 162+ messages in thread
From: Thomas Gleixner @ 2019-11-16 11:25 UTC (permalink / raw)
  To: Stephan Müller
  Cc: Arnd Bergmann, Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

[-- Attachment #1: Type: text/plain, Size: 964 bytes --]

On Sat, 16 Nov 2019, Stephan Müller wrote:
> +/**
> + * Hot code path - Callback for interrupt handler
> + */
> +void add_interrupt_randomness(int irq, int irq_flags)
> +{
> +	lrng_time_process();
> +
> +	if (!lrng_pool_highres_timer()) {
> +		struct pt_regs *regs = get_irq_regs();
> +		static atomic_t reg_idx = ATOMIC_INIT(0);
> +		u64 ip;
> +
> +		lrng_pool_lfsr_u32(jiffies);
> +		lrng_pool_lfsr_u32(irq);
> +		lrng_pool_lfsr_u32(irq_flags);
> +
> +		if (regs) {
> +			u32 *ptr = (u32 *)regs;
> +			int reg_ptr = atomic_add_return_relaxed(1, &reg_idx);
> +			size_t n = (sizeof(struct pt_regs) / sizeof(u32));
> +
> +			ip = instruction_pointer(regs);
> +			lrng_pool_lfsr_u32(*(ptr + (reg_ptr % n)));
> +		} else
> +			ip = _RET_IP_;
> +
> +		lrng_pool_lfsr_u32(ip >> 32);
> +		lrng_pool_lfsr_u32(ip);
> +	}

Is there a way to avoid all that processing right in the interrupt hot
path and just store the raw data for later processing?

Thanks,

	tglx

     

^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v25 10/12] LRNG - add TRNG support
  2019-11-16  9:37   ` [PATCH v25 10/12] LRNG - add TRNG support Stephan Müller
@ 2019-11-16 16:09     ` Andy Lutomirski
  2019-11-17 11:10       ` Stephan Müller
  0 siblings, 1 reply; 162+ messages in thread
From: Andy Lutomirski @ 2019-11-16 16:09 UTC (permalink / raw)
  To: Stephan Müller
  Cc: Arnd Bergmann, Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman



> On Nov 16, 2019, at 1:40 AM, Stephan Müller <smueller@chronox.de> wrote:
> 
> The True Random Number Generator (TRNG) provides a random number
> generator with prediction resistance (SP800-90A terminology) or an NTG.1
> (AIS 31 terminology).
> 

...

> The secondary DRNGs seed from the TRNG if it is present. In addition,
> the /dev/random device accesses the TRNG.
> 
> If the TRNG is disabled, the secondary DRNGs seed from the entropy pool
> and /dev/random behaves like getrandom(2).

As mentioned before, I don’t like this API.  An application that, for some reason, needs a TRNG, should have an API by which it either gets a TRNG or an error. Similarly, an application that wants cryptographically secure random numbers efficiently should have an API that does that.  With your design, /dev/random tries to cater to both use cases, but one of the use cases fails depending on kernel config.

I think /dev/random should wait for enough entropy to initialize the system but should not block after that. A TRNG should have an entirely new API that is better than /dev/random.

^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v25 03/12] LRNG - /proc interface
  2019-11-16  9:34   ` [PATCH v25 03/12] LRNG - /proc interface Stephan Müller
@ 2019-11-16 16:39     ` Andy Lutomirski
  2019-11-17 12:16       ` Stephan Müller
  2019-11-16 23:36     ` Eric W. Biederman
  1 sibling, 1 reply; 162+ messages in thread
From: Andy Lutomirski @ 2019-11-16 16:39 UTC (permalink / raw)
  To: Stephan Müller
  Cc: Arnd Bergmann, Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman


> On Nov 16, 2019, at 1:40 AM, Stephan Müller <smueller@chronox.de> wrote:
> 
> The LRNG /proc interface provides the same files as the legacy
> /dev/random. These files behave identically. Yet, all files are
> documented at [1].

Why?


^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v25 12/12] LRNG - add interface for gathering of raw entropy
  2019-11-16  9:38   ` [PATCH v25 12/12] LRNG - add interface for gathering of raw entropy Stephan Müller
@ 2019-11-16 16:51     ` Andy Lutomirski
  2019-11-17 22:55       ` Stephan Müller
  2019-11-19 17:17     ` Randy Dunlap
  2019-11-21 12:18     ` Nicolai Stange
  2 siblings, 1 reply; 162+ messages in thread
From: Andy Lutomirski @ 2019-11-16 16:51 UTC (permalink / raw)
  To: Stephan Müller
  Cc: Arnd Bergmann, Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman



> On Nov 16, 2019, at 1:40 AM, Stephan Müller <smueller@chronox.de> wrote:
> 
> The test interface allows a privileged process to capture the raw
> unconditioned noise that is collected by the LRNG for statistical
> analysis. Extracted noise data is not used to seed the LRNG. This
> is a test interface and not appropriate for production systems.
> Yet, the interface is considered to be sufficiently secured for
> production systems.
> 
> Access to the data is given through the lrng_raw debugfs file. The
> data buffer should be multiples of sizeof(u32) to fill the entire
> buffer. Using the option lrng_testing.boot_test=1 the raw noise of
> the first 1000 entropy events since boot can be sampled.
> 
> This test interface allows generating the data required for
> analysis whether the LRNG is in compliance with SP800-90B
> sections 3.1.3 and 3.1.4.
> 
> CC: "Eric W. Biederman" <ebiederm@xmission.com>
> CC: "Alexander E. Patrakov" <patrakov@gmail.com>
> CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
> CC: "Theodore Y. Ts'o" <tytso@mit.edu>
> CC: Willy Tarreau <w@1wt.eu>
> CC: Matthew Garrett <mjg59@srcf.ucam.org>
> CC: Vito Caputo <vcaputo@pengaru.com>
> CC: Andreas Dilger <adilger.kernel@dilger.ca>
> CC: Jan Kara <jack@suse.cz>
> CC: Ray Strode <rstrode@redhat.com>
> CC: William Jon McCann <mccann@jhu.edu>
> CC: zhangjs <zachary@baishancloud.com>
> CC: Andy Lutomirski <luto@kernel.org>
> CC: Florian Weimer <fweimer@redhat.com>
> CC: Lennart Poettering <mzxreary@0pointer.de>
> CC: Nicolai Stange <nstange@suse.de>
> Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
> Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
> Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
> Tested-by: Neil Horman <nhorman@redhat.com>
> Signed-off-by: Stephan Mueller <smueller@chronox.de>
> ---
> drivers/char/lrng/Kconfig        |  16 ++
> drivers/char/lrng/Makefile       |   1 +
> drivers/char/lrng/lrng_testing.c | 324 +++++++++++++++++++++++++++++++
> 3 files changed, 341 insertions(+)
> create mode 100644 drivers/char/lrng/lrng_testing.c
> 
> diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
> index e6ca3acc1e48..4ccc710832ef 100644
> --- a/drivers/char/lrng/Kconfig
> +++ b/drivers/char/lrng/Kconfig
> @@ -169,4 +169,20 @@ config LRNG_APT_CUTOFF
>    default 325 if !LRNG_APT_BROKEN
>    default 32 if LRNG_APT_BROKEN
> 
> +config LRNG_TESTING
> +    bool "Enable entropy test interface to LRNG noise source"
> +    select CONFIG_DEBUG_FS
> +    help
> +      The test interface allows a privileged process to capture
> +      the raw unconditioned noise that is collected by the LRNG
> +      for statistical analysis. Extracted noise data is not used
> +      to seed the LRNG.
> +
> +      The raw noise data can be obtained using the lrng_raw
> +      debugfs file. Using the option lrng_testing.boot_test=1
> +      the raw noise of the first 1000 entropy events since boot
> +      can be sampled.
> +
> +      If unsure, say N.
> +
> endif # LRNG
> diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
> index 0713e9c0aa6e..c0b6cc4301fe 100644
> --- a/drivers/char/lrng/Makefile
> +++ b/drivers/char/lrng/Makefile
> @@ -16,3 +16,4 @@ obj-$(CONFIG_LRNG_KCAPI)    += lrng_kcapi.o
> obj-$(CONFIG_LRNG_JENT)        += lrng_jent.o
> obj-$(CONFIG_LRNG_TRNG_SUPPORT)    += lrng_trng.o
> obj-$(CONFIG_LRNG_HEALTH_TESTS)    += lrng_health.o
> +obj-$(CONFIG_LRNG_TESTING)    += lrng_testing.o
> diff --git a/drivers/char/lrng/lrng_testing.c b/drivers/char/lrng/lrng_testing.c
> new file mode 100644
> index 000000000000..5c33d3bd2172
> --- /dev/null
> +++ b/drivers/char/lrng/lrng_testing.c
> @@ -0,0 +1,324 @@
> +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
> +/*
> + * Linux Random Number Generator (LRNG) Raw entropy collection tool
> + *
> + * Copyright (C) 2019, Stephan Mueller <smueller@chronox.de>
> + */
> +
> +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> +
> +#include <linux/atomic.h>
> +#include <linux/bug.h>
> +#include <linux/debugfs.h>
> +#include <linux/module.h>
> +#include <linux/sched.h>
> +#include <linux/sched/signal.h>
> +#include <linux/slab.h>
> +#include <linux/string.h>
> +#include <linux/types.h>
> +#include <linux/uaccess.h>
> +#include <linux/workqueue.h>
> +#include <asm/errno.h>
> +
> +#include "lrng_internal.h"
> +
> +#define LRNG_TESTING_RINGBUFFER_SIZE    1024
> +#define LRNG_TESTING_RINGBUFFER_MASK    (LRNG_TESTING_RINGBUFFER_SIZE - 1)
> +
> +static u32 lrng_testing_rb[LRNG_TESTING_RINGBUFFER_SIZE];
> +static atomic_t lrng_rb_reader = ATOMIC_INIT(0);
> +static atomic_t lrng_rb_writer = ATOMIC_INIT(0);
> +static atomic_t lrng_rb_first_in = ATOMIC_INIT(0);
> +static atomic_t lrng_testing_enabled = ATOMIC_INIT(0);
> +
> +static DECLARE_WAIT_QUEUE_HEAD(lrng_raw_read_wait);
> +
> +static u32 boot_test = 0;
> +module_param(boot_test, uint, 0644);
> +MODULE_PARM_DESC(boot_test, "Enable gathering boot time entropy of the first"
> +                " entropy events");
> +
> +static inline void lrng_raw_entropy_reset(void)
> +{
> +    atomic_set(&lrng_rb_reader, 0);
> +    atomic_set(&lrng_rb_writer, 0);
> +    atomic_set(&lrng_rb_first_in, 0);
> +}
> +
> +static void lrng_raw_entropy_init(void)
> +{
> +    /*
> +     * The boot time testing implies we have a running test. If the
> +     * caller wants to clear it, he has to unset the boot_test flag
> +     * at runtime via sysfs to enable regular runtime testing
> +     */
> +    if (boot_test)
> +        return;
> +
> +    lrng_raw_entropy_reset();
> +    atomic_set(&lrng_testing_enabled, 1);
> +    pr_warn("Enabling raw entropy collection\n");
> +}
> +
> +static void lrng_raw_entropy_fini(void)
> +{
> +    if (boot_test)
> +        return;
> +
> +    lrng_raw_entropy_reset();
> +    atomic_set(&lrng_testing_enabled, 0);
> +    pr_warn("Disabling raw entropy collection\n");
> +}
> +
> +bool lrng_raw_entropy_store(u32 value)
> +{
> +    unsigned int write_ptr;
> +    unsigned int read_ptr;
> +
> +    if (!atomic_read(&lrng_testing_enabled) && !boot_test)
> +        return false;
> +
> +    write_ptr = (unsigned int)atomic_add_return_relaxed(1, &lrng_rb_writer);
> +    read_ptr = (unsigned int)atomic_read(&lrng_rb_reader);

Am I correct in assuming that this function can be called concurrently in different threads or CPUs?

> +
> +    /*
> +     * Disable entropy testing for boot time testing after ring buffer
> +     * is filled.
> +     */
> +    if (boot_test && write_ptr > LRNG_TESTING_RINGBUFFER_SIZE) {
> +        pr_warn_once("Boot time entropy collection test disabled\n");
> +        return false;
> +    }
> +
> +    if (boot_test && !atomic_read(&lrng_rb_first_in))
> +        pr_warn("Boot time entropy collection test enabled\n");
> +
> +    lrng_testing_rb[write_ptr & LRNG_TESTING_RINGBUFFER_MASK] = value;

You’re writing *somewhere*, but not necessarily to the first open slot.

> +
> +    /* We got at least one event, enable the reader now. */
> +    atomic_set(&lrng_rb_first_in, 1);

But not necessarily in position 0.

> +
> +    if (wq_has_sleeper(&lrng_raw_read_wait))
> +        wake_up_interruptible(&lrng_raw_read_wait);
> +
> +    /*
> +     * Our writer is taking over the reader - this means the reader
> +     * one full ring buffer available. Thus we "push" the reader ahead
> +     * to guarantee that he will be able to consume the full ring.
> +     */
> +    if (!boot_test &&
> +        ((write_ptr & LRNG_TESTING_RINGBUFFER_MASK) ==
> +        (read_ptr & LRNG_TESTING_RINGBUFFER_MASK)))
> +        atomic_inc_return_relaxed(&lrng_rb_reader);

Because you did a relaxed increment above, you don’t actually know this. Maybe it’s okay, but this is way too subtle.

I think you should have a mutex for the read side and put all the complicated accounting inside the mutex.  If the reader can’t figure out that the read pointer is too far behind the write pointer, then fix the reader.

I also don’t see how the reader is supposed to know how much data has actually been written.  You don’t have any variable that says “all words up to X have been written”.

I think you should stop trying to make the write side wait free. Instead, consider either using a lock or making it unreliable.  For the former, just skip taking the lock if testing is off. For the latter, read write_ptr, write (using WRITE_ONCE) your data, then cmpxchg the write ptr from the value you read to that value plus one.  And make sure that the reader never tries to read the first unwritten slot, i.e. never let the reader catch all the way up.

I’m also curious why you need entirely different infrastructure for testing as for normal operation.

> +
> +    return true;
> +}
> +
> +static inline bool lrng_raw_have_data(void)
> +{
> +    unsigned int read_ptr = (unsigned int)atomic_read(&lrng_rb_reader);
> +    unsigned int write_ptr = (unsigned int)atomic_read(&lrng_rb_writer);
> +
> +    return (atomic_read(&lrng_rb_first_in) &&
> +        (write_ptr & LRNG_TESTING_RINGBUFFER_MASK) !=
> +         (read_ptr & LRNG_TESTING_RINGBUFFER_MASK));
> +}
> +
> +static int lrng_raw_entropy_reader(u8 *outbuf, u32 outbuflen)
> +{
> +    int collected_data = 0;
> +
> +    if (!atomic_read(&lrng_testing_enabled) && !boot_test)
> +        return -EAGAIN;
> +
> +    if (!atomic_read(&lrng_rb_first_in)) {
> +        wait_event_interruptible(lrng_raw_read_wait,
> +                     lrng_raw_have_data());
> +        if (signal_pending(current))
> +            return -ERESTARTSYS;
> +    }
> +
> +    while (outbuflen) {
> +        unsigned int read_ptr =
> +            (unsigned int)atomic_add_return_relaxed(
> +                            1, &lrng_rb_reader);
> +        unsigned int write_ptr =
> +            (unsigned int)atomic_read(&lrng_rb_writer);
> +
> +        /*
> +         * For boot time testing, only output one round of ring buffer.
> +         */
> +        if (boot_test && read_ptr > LRNG_TESTING_RINGBUFFER_SIZE) {
> +            collected_data = -ENOMSG;
> +            goto out;
> +        }
> +
> +        /* We reached the writer */
> +        if (!boot_test && ((write_ptr & LRNG_TESTING_RINGBUFFER_MASK) ==
> +            (read_ptr & LRNG_TESTING_RINGBUFFER_MASK))) {
> +          

This is wrong. The fact that you haven’t reached the writer does not imply that you’re about to read valid data.


^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v25 01/12] Linux Random Number Generator
  2019-11-16  9:33   ` [PATCH v25 01/12] Linux Random Number Generator Stephan Müller
  2019-11-16 11:25     ` Thomas Gleixner
@ 2019-11-16 18:13     ` Nicolai Stange
  2019-11-17 11:01       ` Stephan Müller
  1 sibling, 1 reply; 162+ messages in thread
From: Nicolai Stange @ 2019-11-16 18:13 UTC (permalink / raw)
  To: Stephan Müller
  Cc: Arnd Bergmann, Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

Hi Stephan,

Stephan Müller <smueller@chronox.de> writes:

> +/* Initialize the default DRNG during boot */

I think that this can get called a bit too early through the
get_random_bytes() invoked from e.g. boot_init_stack_canary(): in
start_kernel(), there is

	boot_init_stack_canary();

	time_init();

On ARM (at least with arm_arch_timer.c), get_cycles() would return 0
until

  time_init() => timer_probe() => arch_timer_of_init() =>
  arch_timer_common_init() => arch_timer_arch_init() =>
  arch_timer_delay_timer_register() => register_current_timer_delay()

has executed and thus, ...

> +void lrng_drngs_init_cc20(void)
> +{
> +	unsigned long flags = 0;
> +
> +	if (lrng_get_available())
> +		return;
> +
> +	lrng_sdrng_lock(&lrng_sdrng_init, &flags);
> +	if (lrng_get_available()) {
> +		lrng_sdrng_unlock(&lrng_sdrng_init, &flags);
> +		return;
> +	}
> +
> +	if (random_get_entropy() || random_get_entropy()) {
> +		/*
> +		 * As the highres timer is identified here, previous interrupts
> +		 * obtained during boot time are treated like a lowres-timer
> +		 * would have been present.
> +		 */
> +		lrng_pool_configure(true, LRNG_IRQ_ENTROPY_BITS);
> +	} else {
> +		lrng_health_disable();
> +		lrng_pool_configure(false, LRNG_IRQ_ENTROPY_BITS *
> +					   LRNG_IRQ_OVERSAMPLING_FACTOR);
> +		pr_warn("operating without high-resolution timer and applying "
> +			"IRQ oversampling factor %u\n",
> +			LRNG_IRQ_OVERSAMPLING_FACTOR);


... LRNG thinks that no high-res timer is available even though there
is:

[    0.000000] lrng_sdrng: operating without high-resolution timer and applying IRQ oversampling factor 10
[    0.000000] lrng_chacha20: ChaCha20 core initialized
[    0.000000] lrng_chacha20: ChaCha20 core initialized
[    0.000014] sched_clock: 32 bits at 1000kHz, resolution 1000ns, wraps every 2147483647500ns
[    0.000036] clocksource: timer: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 1911260446275 ns
[    0.000114] bcm2835: system timer (irq = 27)
[    0.000594] arch_timer: cp15 timer(s) running at 19.20MHz (phys).
[    0.000613] clocksource: arch_sys_counter: mask: 0xffffffffffffff max_cycles: 0x46d987e47, max_idle_ns: 440795202767 ns
[    0.000631] sched_clock: 56 bits at 19MHz, resolution 52ns, wraps every 4398046511078ns
[    0.000645] Switching to timer-based delay loop, resolution 52ns

Note that this last line comes from aforementioned
register_current_timer_delay().

Similarly, get_random_bytes() can get called quite early through
WARN() => warn_slowpath_fmt() => __warn() => print_oops_end_marker() =>
init_oops_id().

Perhaps it would make sense not to do the (pool + health test)
initalization "on-demand", but rather make sure it happens at some
well-defined point after time_init()? Or at least that the pool +
the health tests get reconfigured eventually?


Thanks,

Nicolai

P.S: include/linux/lrng.h needs an #include <linux/errno.h> for
     CONFIG_LRNG_DRNG_SWITCH=n


> +	}
> +
> +	lrng_sdrng_reset(&lrng_sdrng_init);
> +	lrng_cc20_init_state(&secondary_chacha20);
> +	lrng_state_init_seed_work();
> +	lrng_sdrng_unlock(&lrng_sdrng_init, &flags);
> +
> +	lrng_sdrng_lock(&lrng_sdrng_atomic, &flags);
> +	lrng_sdrng_reset(&lrng_sdrng_atomic);
> +	/*
> +	 * We do not initialize the state of the atomic DRNG as it is identical
> +	 * to the secondary DRNG at this point.
> +	 */
> +	lrng_sdrng_unlock(&lrng_sdrng_atomic, &flags);
> +
> +	lrng_trng_init();
> +
> +	lrng_set_available();
> +}
> +
> +/* Reset LRNG such that all existing entropy is gone */

-- 
SUSE Software Solutions Germany GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg), GF: Felix Imendörffer

^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v25 03/12] LRNG - /proc interface
  2019-11-16  9:34   ` [PATCH v25 03/12] LRNG - /proc interface Stephan Müller
  2019-11-16 16:39     ` Andy Lutomirski
@ 2019-11-16 23:36     ` Eric W. Biederman
  2019-11-17 11:37       ` Stephan Müller
  1 sibling, 1 reply; 162+ messages in thread
From: Eric W. Biederman @ 2019-11-16 23:36 UTC (permalink / raw)
  To: Stephan Müller
  Cc: Arnd Bergmann, Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Alexander E. Patrakov, Ahmed S. Darwish, Theodore Y. Ts'o,
	Willy Tarreau, Matthew Garrett, Vito Caputo, Andreas Dilger,
	Jan Kara, Ray Strode, William Jon McCann, zhangjs,
	Andy Lutomirski, Florian Weimer, Lennart Poettering,
	Nicolai Stange, Peter, Matthias, Marcelo Henrique Cerri,
	Roman Drahtmueller, Neil Horman

Stephan Müller <smueller@chronox.de> writes:

> The LRNG /proc interface provides the same files as the legacy
> /dev/random. These files behave identically. Yet, all files are
> documented at [1].

For someone who works in this area a lot this description is confusing.

You are talking about sysctls not ordinary proc files.

You don't have a call register_sysctl.  If you want your own
implementation of these sysctls that would seem to be the way to get
them.  Teach each implementation to register their own set of sysctls
if they are enabled.

The entire structure of the code you are adding I have quite confusing,
and a bit messing.

Why add a declaration of random_table in patch 1 and then delete that
declaration in patch 3?  Nothing uses that declaration until this point.

What is the point of adding an extern declaration just before you
declare the table itself?  As I understand the C language that achieves
nothing.  I understand that is what the existing code in
drivers/char/random.c does but that is equally buggy there.

I also don't understand why you don't modify the existing random
generator code into the form you want?  What is the point of a
side-by-side replacement?  Especially since only one of them can
be compiled into the kernel at the same time?

This build a replacement and then switch over seems like a recipe for
loosing the lessons of history because you are not making incremental
changes that can be clearly understood, reviewed and bisected.

As I read your patchset until this change your code will fail to compile
in an ordinary configuration with proc enabled.  Have you even tested
compiling your patchset one patch at a time?

For me a great reorganization to impelment a better structure that fails
to have a good structure on the usual merits makes me dubious about the
entire thing.  As it can be a sign the author was pushing so hard to
make things work he stopped looking at problematic details.

Dubious-by: "Eric W. Biederman" <ebiederm@xmission.com>

Eric

> +
> +extern struct ctl_table random_table[];
> +struct ctl_table random_table[] = {
> +	{

^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v25 01/12] Linux Random Number Generator
  2019-11-16 11:25     ` Thomas Gleixner
@ 2019-11-17 10:30       ` Stephan Müller
  0 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-17 10:30 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Arnd Bergmann, Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

Am Samstag, 16. November 2019, 12:25:21 CET schrieb Thomas Gleixner:

Hi Thomas,

> On Sat, 16 Nov 2019, Stephan Müller wrote:
> > +/**
> > + * Hot code path - Callback for interrupt handler
> > + */
> > +void add_interrupt_randomness(int irq, int irq_flags)
> > +{
> > +	lrng_time_process();
> > +
> > +	if (!lrng_pool_highres_timer()) {
> > +		struct pt_regs *regs = get_irq_regs();
> > +		static atomic_t reg_idx = ATOMIC_INIT(0);
> > +		u64 ip;
> > +
> > +		lrng_pool_lfsr_u32(jiffies);
> > +		lrng_pool_lfsr_u32(irq);
> > +		lrng_pool_lfsr_u32(irq_flags);
> > +
> > +		if (regs) {
> > +			u32 *ptr = (u32 *)regs;
> > +			int reg_ptr = atomic_add_return_relaxed(1, &reg_idx);
> > +			size_t n = (sizeof(struct pt_regs) / sizeof(u32));
> > +
> > +			ip = instruction_pointer(regs);
> > +			lrng_pool_lfsr_u32(*(ptr + (reg_ptr % n)));
> > +		} else
> > +			ip = _RET_IP_;
> > +
> > +		lrng_pool_lfsr_u32(ip >> 32);
> > +		lrng_pool_lfsr_u32(ip);
> > +	}
> 
> Is there a way to avoid all that processing right in the interrupt hot
> path and just store the raw data for later processing?

The main code path is lrng_time_process(). This code is streamlined as you 
already suggested: it is very lightweight to the interrupt handler. Compared 
to the existing /dev/random implementation it is about 50% faster.

When measuring the lrng_time_process, it takes on one particular test system 
on average about 65 cycles where on that very same system the 
add_interrupt_randomness code path from the existing /dev/random takes on 
average about 97 cycles.

The additional code you see in the add_interrupt_randomness is only executed 
if lrng_pool_highres_timer is not set. This is not set if the LRNG does not 
find a high-resolution time stamp, i.e. random_get_entropy() returns 0. As on 
most architectures this is now set, this code path is not executed.

This additional code path serves as an emergency code to collect some data 
that smells random and having entropy but not having really much.

It may be a bit more stremlined but since it is hardly used, I left it as it 
is so far. Do you see the need to streamline it more at this time?

Thanks a lot.


Ciao
Stephan



^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v25 01/12] Linux Random Number Generator
  2019-11-16 18:13     ` Nicolai Stange
@ 2019-11-17 11:01       ` Stephan Müller
  0 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-17 11:01 UTC (permalink / raw)
  To: Nicolai Stange
  Cc: Arnd Bergmann, Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Peter, Matthias, Marcelo Henrique Cerri,
	Roman Drahtmueller, Neil Horman

Am Samstag, 16. November 2019, 19:13:23 CET schrieb Nicolai Stange:

Hi Nicolai,

> Hi Stephan,
> 
> Stephan Müller <smueller@chronox.de> writes:
> > +/* Initialize the default DRNG during boot */
> 
> I think that this can get called a bit too early through the
> get_random_bytes() invoked from e.g. boot_init_stack_canary(): in
> start_kernel(), there is
> 
> 	boot_init_stack_canary();
> 
> 	time_init();
> 
> On ARM (at least with arm_arch_timer.c), get_cycles() would return 0
> until
> 
>   time_init() => timer_probe() => arch_timer_of_init() =>
>   arch_timer_common_init() => arch_timer_arch_init() =>
>   arch_timer_delay_timer_register() => register_current_timer_delay()
> 
> has executed and thus, ...
> 
> > +void lrng_drngs_init_cc20(void)
> > +{
> > +	unsigned long flags = 0;
> > +
> > +	if (lrng_get_available())
> > +		return;
> > +
> > +	lrng_sdrng_lock(&lrng_sdrng_init, &flags);
> > +	if (lrng_get_available()) {
> > +		lrng_sdrng_unlock(&lrng_sdrng_init, &flags);
> > +		return;
> > +	}
> > +
> > +	if (random_get_entropy() || random_get_entropy()) {
> > +		/*
> > +		 * As the highres timer is identified here, previous interrupts
> > +		 * obtained during boot time are treated like a lowres-timer
> > +		 * would have been present.
> > +		 */
> > +		lrng_pool_configure(true, LRNG_IRQ_ENTROPY_BITS);
> > +	} else {
> > +		lrng_health_disable();
> > +		lrng_pool_configure(false, LRNG_IRQ_ENTROPY_BITS *
> > +					   LRNG_IRQ_OVERSAMPLING_FACTOR);
> > +		pr_warn("operating without high-resolution timer and applying "
> > +			"IRQ oversampling factor %u\n",
> > +			LRNG_IRQ_OVERSAMPLING_FACTOR);
> 
> ... LRNG thinks that no high-res timer is available even though there
> is:
> 
> [    0.000000] lrng_sdrng: operating without high-resolution timer and
> applying IRQ oversampling factor 10 [    0.000000] lrng_chacha20: ChaCha20
> core initialized
> [    0.000000] lrng_chacha20: ChaCha20 core initialized
> [    0.000014] sched_clock: 32 bits at 1000kHz, resolution 1000ns, wraps
> every 2147483647500ns [    0.000036] clocksource: timer: mask: 0xffffffff
> max_cycles: 0xffffffff, max_idle_ns: 1911260446275 ns [    0.000114]
> bcm2835: system timer (irq = 27)
> [    0.000594] arch_timer: cp15 timer(s) running at 19.20MHz (phys).
> [    0.000613] clocksource: arch_sys_counter: mask: 0xffffffffffffff
> max_cycles: 0x46d987e47, max_idle_ns: 440795202767 ns [    0.000631]
> sched_clock: 56 bits at 19MHz, resolution 52ns, wraps every 4398046511078ns
> [    0.000645] Switching to timer-based delay loop, resolution 52ns
> 
> Note that this last line comes from aforementioned
> register_current_timer_delay().
> 
> Similarly, get_random_bytes() can get called quite early through
> WARN() => warn_slowpath_fmt() => __warn() => print_oops_end_marker() =>
> init_oops_id().
> 
> Perhaps it would make sense not to do the (pool + health test)
> initalization "on-demand", but rather make sure it happens at some
> well-defined point after time_init()? Or at least that the pool +
> the health tests get reconfigured eventually?


Thank you very much for testing this and reporting it.

I have extracted the initialization of the time source into its own function 
and execute it with core_initcall. With that, the DRNG is initialized at the 
time it needs initialization.

But the time source check is now done when time_init is completed as first 
time_init is called and then arch_call_rest_init -> rest_init -> kernel_init -
> kernel_init_freeable -> do_basic_setup -> do_initcalls where the initcalls 
registered with the core_initcall callback are now executed as the first 
batch.


> 
> 
> Thanks,
> 
> Nicolai
> 
> P.S: include/linux/lrng.h needs an #include <linux/errno.h> for
>      CONFIG_LRNG_DRNG_SWITCH=n

Thank you, added.
> 
> > +	}
> > +
> > +	lrng_sdrng_reset(&lrng_sdrng_init);
> > +	lrng_cc20_init_state(&secondary_chacha20);
> > +	lrng_state_init_seed_work();
> > +	lrng_sdrng_unlock(&lrng_sdrng_init, &flags);
> > +
> > +	lrng_sdrng_lock(&lrng_sdrng_atomic, &flags);
> > +	lrng_sdrng_reset(&lrng_sdrng_atomic);
> > +	/*
> > +	 * We do not initialize the state of the atomic DRNG as it is identical
> > +	 * to the secondary DRNG at this point.
> > +	 */
> > +	lrng_sdrng_unlock(&lrng_sdrng_atomic, &flags);
> > +
> > +	lrng_trng_init();
> > +
> > +	lrng_set_available();
> > +}
> > +
> > +/* Reset LRNG such that all existing entropy is gone */


Ciao
Stephan



^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v25 10/12] LRNG - add TRNG support
  2019-11-16 16:09     ` Andy Lutomirski
@ 2019-11-17 11:10       ` Stephan Müller
  2019-11-19 10:07         ` Andy Lutomirski
  0 siblings, 1 reply; 162+ messages in thread
From: Stephan Müller @ 2019-11-17 11:10 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Arnd Bergmann, Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

Am Samstag, 16. November 2019, 17:09:09 CET schrieb Andy Lutomirski:

Hi Andy,

> > On Nov 16, 2019, at 1:40 AM, Stephan Müller <smueller@chronox.de> wrote:
> > 
> > The True Random Number Generator (TRNG) provides a random number
> > generator with prediction resistance (SP800-90A terminology) or an NTG.1
> > (AIS 31 terminology).
> 
> ...
> 
> > The secondary DRNGs seed from the TRNG if it is present. In addition,
> > the /dev/random device accesses the TRNG.
> > 
> > If the TRNG is disabled, the secondary DRNGs seed from the entropy pool
> > and /dev/random behaves like getrandom(2).
> 
> As mentioned before, I don’t like this API.  An application that, for some
> reason, needs a TRNG, should have an API by which it either gets a TRNG or
> an error. Similarly, an application that wants cryptographically secure
> random numbers efficiently should have an API that does that.  With your
> design, /dev/random tries to cater to both use cases, but one of the use
> cases fails depending on kernel config.
> 
> I think /dev/random should wait for enough entropy to initialize the system
> but should not block after that. A TRNG should have an entirely new API
> that is better than /dev/random.

I apologize for the misunderstanding. I assumed we would introduce such /dev/
true_random at a later stage.

If you agree, I can certainly add /dev/true_random right now that links with 
the TRNG and make /dev/random behave as discussed, i.e. behave exactly like 
getrandom(..., 0);

As this would introduce a new device file now, is there a special process that 
I need to follow or do I need to copy? Which major/minor number should I use?

Looking into static const struct memdev devlist[] I see

         [8] = { "random", 0666, &random_fops, 0 },
         [9] = { "urandom", 0666, &urandom_fops, 0 },

Shall a true_random be added here with [10]?

Ciao
Stephan



^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v25 03/12] LRNG - /proc interface
  2019-11-16 23:36     ` Eric W. Biederman
@ 2019-11-17 11:37       ` Stephan Müller
  0 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-17 11:37 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: Arnd Bergmann, Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Alexander E. Patrakov, Ahmed S. Darwish, Theodore Y. Ts'o,
	Willy Tarreau, Matthew Garrett, Vito Caputo, Andreas Dilger,
	Jan Kara, Ray Strode, William Jon McCann, zhangjs,
	Andy Lutomirski, Florian Weimer, Lennart Poettering,
	Nicolai Stange, Peter, Matthias, Marcelo Henrique Cerri,
	Roman Drahtmueller, Neil Horman

Am Sonntag, 17. November 2019, 00:36:25 CET schrieb Eric W. Biederman:

Hi Eric,

> Stephan Müller <smueller@chronox.de> writes:
> > The LRNG /proc interface provides the same files as the legacy
> > /dev/random. These files behave identically. Yet, all files are
> > documented at [1].
> 
> For someone who works in this area a lot this description is confusing.
> 
> You are talking about sysctls not ordinary proc files.

Agreed and I will change the description accordingly.
> 
> You don't have a call register_sysctl.  If you want your own
> implementation of these sysctls that would seem to be the way to get
> them.  Teach each implementation to register their own set of sysctls
> if they are enabled.

Agreed, I will do that.
> 
> The entire structure of the code you are adding I have quite confusing,
> and a bit messing.
> 
> Why add a declaration of random_table in patch 1 and then delete that
> declaration in patch 3?  Nothing uses that declaration until this point.

This is only to ensure that patch 1 compiles. Without it, there would be a 
dangling reference that is required by static struct ctl_table kern_table[].

As I was always under the impression that each patch should compile by itself 
to support bisect, I added that empty declaration. Yet, patch 1 is never 
intended to live without patch 3. I only split patch 3 up is to aid code 
review by having as many individual patches as possible while still allowing 
them to compile.
> 
> What is the point of adding an extern declaration just before you
> declare the table itself?  As I understand the C language that achieves
> nothing.  I understand that is what the existing code in
> drivers/char/random.c does but that is equally buggy there.

I totally agree and I was wondering here as well. But I simply was taking it 
as is.

I am happy to clean this one up.
> 
> I also don't understand why you don't modify the existing random
> generator code into the form you want?  What is the point of a
> side-by-side replacement?  Especially since only one of them can
> be compiled into the kernel at the same time?

I was developing small patches for random.c since 2013, mostly cleanup 
patches. Unfortunately most of them were silently ignored. Some others were 
silently taken but appeared two or three kernel releases later.

Getting more architecture-invasive patches into the existing random.c code is 
considered to be quite a problem considering this experience.

Besides, the LRNG has quite a different architecture compared to the random.c. 
As the RNG is an important aspect of the kernel, I did not feel bold enough to 
simply replace the existing code which implies that there is no fallback. By 
allowing a side-by-side code base which is even deactivated by default, it 
allows other researchers to analyze the mathematical aspects beyond the pure 
code while still having an implementation that provides a known and analyzed 
entropy source.

Also, considering other kernel components like memory allocators, I/O 
schedulers or even file systems, providing different architectures covering 
similar problems (memory allocation, accessing a disk) with an entirely 
different architecture and thus implementation seems to be an appropriate 
solution.

Finally, I tried to keep code that has a similar functionality to the existing 
random.c similar to allow a merge at a later stage. For example, the sysctls 
are identical, but internally use different variables.
> 
> This build a replacement and then switch over seems like a recipe for
> loosing the lessons of history because you are not making incremental
> changes that can be clearly understood, reviewed and bisected.
> 
> As I read your patchset until this change your code will fail to compile
> in an ordinary configuration with proc enabled.  Have you even tested
> compiling your patchset one patch at a time?

Yes, it does compile with proc enabled with the warning that random_table is 
considered to contain one element.
> 
> For me a great reorganization to impelment a better structure that fails
> to have a good structure on the usual merits makes me dubious about the
> entire thing.  As it can be a sign the author was pushing so hard to
> make things work he stopped looking at problematic details.
> 
> Dubious-by: "Eric W. Biederman" <ebiederm@xmission.com>
> 
> Eric
> 
> > +
> > +extern struct ctl_table random_table[];
> > +struct ctl_table random_table[] = {
> > +	{


Ciao
Stephan



^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v25 03/12] LRNG - /proc interface
  2019-11-16 16:39     ` Andy Lutomirski
@ 2019-11-17 12:16       ` Stephan Müller
  2019-11-19 10:06         ` Andy Lutomirski
  0 siblings, 1 reply; 162+ messages in thread
From: Stephan Müller @ 2019-11-17 12:16 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Arnd Bergmann, Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

Am Samstag, 16. November 2019, 17:39:40 CET schrieb Andy Lutomirski:

Hi Andy,

> > On Nov 16, 2019, at 1:40 AM, Stephan Müller <smueller@chronox.de> wrote:
> > 
> > The LRNG /proc interface provides the same files as the legacy
> > /dev/random. These files behave identically. Yet, all files are
> > documented at [1].
> 
> Why?

I am not sure here: are you referring to the documentation? Or the one 
additional file?

If it is the documentation, do you want me to add it to the patch description? 
I initially did not add it as these files were present and seemingly known 
what they provide. But I would add that documentation to the patch description 
if this is desired.

If it is the additional file, should I move it to another place like a sysfs 
interface?

Thank you.

Ciao
Stephan



^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v25 12/12] LRNG - add interface for gathering of raw entropy
  2019-11-16 16:51     ` Andy Lutomirski
@ 2019-11-17 22:55       ` Stephan Müller
  2019-11-19 10:04         ` Andy Lutomirski
  0 siblings, 1 reply; 162+ messages in thread
From: Stephan Müller @ 2019-11-17 22:55 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Arnd Bergmann, Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

Am Samstag, 16. November 2019, 17:51:24 CET schrieb Andy Lutomirski:

Hi Andy,

> > On Nov 16, 2019, at 1:40 AM, Stephan Müller <smueller@chronox.de> wrote:
> > 
> > The test interface allows a privileged process to capture the raw
> > unconditioned noise that is collected by the LRNG for statistical
> > analysis. Extracted noise data is not used to seed the LRNG. This
> > is a test interface and not appropriate for production systems.
> > Yet, the interface is considered to be sufficiently secured for
> > production systems.
> > 
> > Access to the data is given through the lrng_raw debugfs file. The
> > data buffer should be multiples of sizeof(u32) to fill the entire
> > buffer. Using the option lrng_testing.boot_test=1 the raw noise of
> > the first 1000 entropy events since boot can be sampled.
> > 
> > This test interface allows generating the data required for
> > analysis whether the LRNG is in compliance with SP800-90B
> > sections 3.1.3 and 3.1.4.
> > 
> > CC: "Eric W. Biederman" <ebiederm@xmission.com>
> > CC: "Alexander E. Patrakov" <patrakov@gmail.com>
> > CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
> > CC: "Theodore Y. Ts'o" <tytso@mit.edu>
> > CC: Willy Tarreau <w@1wt.eu>
> > CC: Matthew Garrett <mjg59@srcf.ucam.org>
> > CC: Vito Caputo <vcaputo@pengaru.com>
> > CC: Andreas Dilger <adilger.kernel@dilger.ca>
> > CC: Jan Kara <jack@suse.cz>
> > CC: Ray Strode <rstrode@redhat.com>
> > CC: William Jon McCann <mccann@jhu.edu>
> > CC: zhangjs <zachary@baishancloud.com>
> > CC: Andy Lutomirski <luto@kernel.org>
> > CC: Florian Weimer <fweimer@redhat.com>
> > CC: Lennart Poettering <mzxreary@0pointer.de>
> > CC: Nicolai Stange <nstange@suse.de>
> > Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
> > Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
> > Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
> > Tested-by: Neil Horman <nhorman@redhat.com>
> > Signed-off-by: Stephan Mueller <smueller@chronox.de>
> > ---
> > drivers/char/lrng/Kconfig        |  16 ++
> > drivers/char/lrng/Makefile       |   1 +
> > drivers/char/lrng/lrng_testing.c | 324 +++++++++++++++++++++++++++++++
> > 3 files changed, 341 insertions(+)
> > create mode 100644 drivers/char/lrng/lrng_testing.c
> > 
> > diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
> > index e6ca3acc1e48..4ccc710832ef 100644
> > --- a/drivers/char/lrng/Kconfig
> > +++ b/drivers/char/lrng/Kconfig
> > @@ -169,4 +169,20 @@ config LRNG_APT_CUTOFF
> > 
> >    default 325 if !LRNG_APT_BROKEN
> >    default 32 if LRNG_APT_BROKEN
> > 
> > +config LRNG_TESTING
> > +    bool "Enable entropy test interface to LRNG noise source"
> > +    select CONFIG_DEBUG_FS
> > +    help
> > +      The test interface allows a privileged process to capture
> > +      the raw unconditioned noise that is collected by the LRNG
> > +      for statistical analysis. Extracted noise data is not used
> > +      to seed the LRNG.
> > +
> > +      The raw noise data can be obtained using the lrng_raw
> > +      debugfs file. Using the option lrng_testing.boot_test=1
> > +      the raw noise of the first 1000 entropy events since boot
> > +      can be sampled.
> > +
> > +      If unsure, say N.
> > +
> > endif # LRNG
> > diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
> > index 0713e9c0aa6e..c0b6cc4301fe 100644
> > --- a/drivers/char/lrng/Makefile
> > +++ b/drivers/char/lrng/Makefile
> > @@ -16,3 +16,4 @@ obj-$(CONFIG_LRNG_KCAPI)    += lrng_kcapi.o
> > obj-$(CONFIG_LRNG_JENT)        += lrng_jent.o
> > obj-$(CONFIG_LRNG_TRNG_SUPPORT)    += lrng_trng.o
> > obj-$(CONFIG_LRNG_HEALTH_TESTS)    += lrng_health.o
> > +obj-$(CONFIG_LRNG_TESTING)    += lrng_testing.o
> > diff --git a/drivers/char/lrng/lrng_testing.c
> > b/drivers/char/lrng/lrng_testing.c new file mode 100644
> > index 000000000000..5c33d3bd2172
> > --- /dev/null
> > +++ b/drivers/char/lrng/lrng_testing.c
> > @@ -0,0 +1,324 @@
> > +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
> > +/*
> > + * Linux Random Number Generator (LRNG) Raw entropy collection tool
> > + *
> > + * Copyright (C) 2019, Stephan Mueller <smueller@chronox.de>
> > + */
> > +
> > +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> > +
> > +#include <linux/atomic.h>
> > +#include <linux/bug.h>
> > +#include <linux/debugfs.h>
> > +#include <linux/module.h>
> > +#include <linux/sched.h>
> > +#include <linux/sched/signal.h>
> > +#include <linux/slab.h>
> > +#include <linux/string.h>
> > +#include <linux/types.h>
> > +#include <linux/uaccess.h>
> > +#include <linux/workqueue.h>
> > +#include <asm/errno.h>
> > +
> > +#include "lrng_internal.h"
> > +
> > +#define LRNG_TESTING_RINGBUFFER_SIZE    1024
> > +#define LRNG_TESTING_RINGBUFFER_MASK    (LRNG_TESTING_RINGBUFFER_SIZE -
> > 1)
> > +
> > +static u32 lrng_testing_rb[LRNG_TESTING_RINGBUFFER_SIZE];
> > +static atomic_t lrng_rb_reader = ATOMIC_INIT(0);
> > +static atomic_t lrng_rb_writer = ATOMIC_INIT(0);
> > +static atomic_t lrng_rb_first_in = ATOMIC_INIT(0);
> > +static atomic_t lrng_testing_enabled = ATOMIC_INIT(0);
> > +
> > +static DECLARE_WAIT_QUEUE_HEAD(lrng_raw_read_wait);
> > +
> > +static u32 boot_test = 0;
> > +module_param(boot_test, uint, 0644);
> > +MODULE_PARM_DESC(boot_test, "Enable gathering boot time entropy of the
> > first" +                " entropy events");
> > +
> > +static inline void lrng_raw_entropy_reset(void)
> > +{
> > +    atomic_set(&lrng_rb_reader, 0);
> > +    atomic_set(&lrng_rb_writer, 0);
> > +    atomic_set(&lrng_rb_first_in, 0);
> > +}
> > +
> > +static void lrng_raw_entropy_init(void)
> > +{
> > +    /*
> > +     * The boot time testing implies we have a running test. If the
> > +     * caller wants to clear it, he has to unset the boot_test flag
> > +     * at runtime via sysfs to enable regular runtime testing
> > +     */
> > +    if (boot_test)
> > +        return;
> > +
> > +    lrng_raw_entropy_reset();
> > +    atomic_set(&lrng_testing_enabled, 1);
> > +    pr_warn("Enabling raw entropy collection\n");
> > +}
> > +
> > +static void lrng_raw_entropy_fini(void)
> > +{
> > +    if (boot_test)
> > +        return;
> > +
> > +    lrng_raw_entropy_reset();
> > +    atomic_set(&lrng_testing_enabled, 0);
> > +    pr_warn("Disabling raw entropy collection\n");
> > +}
> > +
> > +bool lrng_raw_entropy_store(u32 value)
> > +{
> > +    unsigned int write_ptr;
> > +    unsigned int read_ptr;
> > +
> > +    if (!atomic_read(&lrng_testing_enabled) && !boot_test)
> > +        return false;
> > +
> > +    write_ptr = (unsigned int)atomic_add_return_relaxed(1,
> > &lrng_rb_writer); +    read_ptr = (unsigned
> > int)atomic_read(&lrng_rb_reader);

Before answering your comments, please allow me to clarify the following:

This entire code is intended to obtain take raw unconditioned noise data that 
needs to be extracted from the kernel to user space to allow it to be further 
analyzed. This is also why it is mentioned in the Kconfig selection that in 
doubt one should select N and that this code is not intended for production 
kernels although this code should be secure enough to be present in production 
kernels.

For example, raw unconditioned noise data needs to be processed by the 
complicated math outlined in chapter 6 of [1]. For that, there is a tool 
available, see [2]. For that tool, data is needed that is obtained with the 
getrawentropy tool available with [3] where this tool obtains the data from 
the SysFS file that is implemented with this C file.

In addition, [1] even needs the data from the very first 1000 interrupts after 
boot. Hence, the LRNG needs to be able to store that data until user space can 
pick it up (see the boot_test variable).

The assessment resulting from this can be reviewed at [4] section 3.2 In 
particular, the numbers provided at the end of sections 3.2.3 and 3.2.4 are 
obtained with this interface. 

Other examples where such raw unconditioned noise data is needed for further 
analysis is [5], especially chapter 6.

This testing has nothing to do with the runtime testing provided with the 
patch set 11. All data that ends up here is not available to the LRNG and will 
not contribute to any entropy collection.

See the following:

static inline void lrng_time_process(void)
{
...
	if (lrng_raw_entropy_store(now_time))
		return;


bool lrng_raw_entropy_store(u32 value)
{
...
	if (!atomic_read(&lrng_testing_enabled) && !boot_test)
		return false;
...
	return true;

> 
> Am I correct in assuming that this function can be called concurrently in
> different threads or CPUs?

Yes, because it is called indirectly by add_interrupt_randomness.
> > +
> > +    /*
> > +     * Disable entropy testing for boot time testing after ring buffer
> > +     * is filled.
> > +     */
> > +    if (boot_test && write_ptr > LRNG_TESTING_RINGBUFFER_SIZE) {
> > +        pr_warn_once("Boot time entropy collection test disabled\n");
> > +        return false;
> > +    }
> > +
> > +    if (boot_test && !atomic_read(&lrng_rb_first_in))
> > +        pr_warn("Boot time entropy collection test enabled\n");
> > +
> > +    lrng_testing_rb[write_ptr & LRNG_TESTING_RINGBUFFER_MASK] = value;
> 
> You’re writing *somewhere*, but not necessarily to the first open slot.

The idea is that there is a reader pointer and a writer pointer where the 
reader always must be smaller or equal to the writer (modulo the size of the 
ring buffer). So, I do not care where the writer ptr is.

All I need is that:

1. reader and writer ptr must start with the same value at boot time (e.g. 0)

2. reader ptr is always <= writer ptr in order for data to be read.

With these two conditions, when pulling data from the buffer, I need to pull 
always the data from the reader ptr until the reader ptr reaches the writer 
pointer.

Note, the reader/writer pointers are always set to 0 at the beginning of a new 
read request from user space.

> 
> > +
> > +    /* We got at least one event, enable the reader now. */
> > +    atomic_set(&lrng_rb_first_in, 1);
> 
> But not necessarily in position 0.

Yes, this is perfectly ok.
> 
> > +
> > +    if (wq_has_sleeper(&lrng_raw_read_wait))
> > +        wake_up_interruptible(&lrng_raw_read_wait);
> > +
> > +    /*
> > +     * Our writer is taking over the reader - this means the reader
> > +     * one full ring buffer available. Thus we "push" the reader ahead
> > +     * to guarantee that he will be able to consume the full ring.
> > +     */
> > +    if (!boot_test &&
> > +        ((write_ptr & LRNG_TESTING_RINGBUFFER_MASK) ==
> > +        (read_ptr & LRNG_TESTING_RINGBUFFER_MASK)))
> > +        atomic_inc_return_relaxed(&lrng_rb_reader);
> 
> Because you did a relaxed increment above, you don’t actually know this.
> Maybe it’s okay, but this is way too subtle.

You are absolutely correct, there should be no relaxed atomic operation. We 
should take the atomic_inc above and here.

I fixed this.
> 
> I think you should have a mutex for the read side and put all the
> complicated accounting inside the mutex.  If the reader can’t figure out
> that the read pointer is too far behind the write pointer, then fix the
> reader.

Done - the writer now only writes the data and generates the boot log if the 
boot time raw entropy gathering is enabled.
> 
> I also don’t see how the reader is supposed to know how much data has
> actually been written.  You don’t have any variable that says “all words up
> to X have been written”.

With the two rules above, I think the reader knows that: all data between the 
reader ptr and the writer ptr modulo the size of the ring buffer.

But I simplified the code now, the code now only copies the data out if the 
reader <= writer modulo the ring buffer size. In this case, if the writer is 
much faster, then we loose some values.

With the old code, we simply would have lost it too, but just a bit later.
> 
> I think you should stop trying to make the write side wait free.
> Instead,
> consider either using a lock or making it unreliable.  For the former, just
> skip taking the lock if testing is off. For the latter, read write_ptr,
> write (using WRITE_ONCE) your data, then cmpxchg the write ptr from the
> value you read to that value plus one.  And make sure that the reader never
> tries to read the first unwritten slot, i.e. never let the reader catch all
> the way up.

I have followed the locking approach as we need to get correct data.
> 
> I’m also curious why you need entirely different infrastructure for testing
> as for normal operation.

I hope with the explanation above, the question is answered.


> > +
> > +    return true;
> > +}
> > +
> > +static inline bool lrng_raw_have_data(void)
> > +{
> > +    unsigned int read_ptr = (unsigned int)atomic_read(&lrng_rb_reader);
> > +    unsigned int write_ptr = (unsigned int)atomic_read(&lrng_rb_writer);
> > +
> > +    return (atomic_read(&lrng_rb_first_in) &&
> > +        (write_ptr & LRNG_TESTING_RINGBUFFER_MASK) !=
> > +         (read_ptr & LRNG_TESTING_RINGBUFFER_MASK));
> > +}
> > +
> > +static int lrng_raw_entropy_reader(u8 *outbuf, u32 outbuflen)
> > +{
> > +    int collected_data = 0;
> > +
> > +    if (!atomic_read(&lrng_testing_enabled) && !boot_test)
> > +        return -EAGAIN;
> > +
> > +    if (!atomic_read(&lrng_rb_first_in)) {
> > +        wait_event_interruptible(lrng_raw_read_wait,
> > +                     lrng_raw_have_data());
> > +        if (signal_pending(current))
> > +            return -ERESTARTSYS;
> > +    }
> > +
> > +    while (outbuflen) {
> > +        unsigned int read_ptr =
> > +            (unsigned int)atomic_add_return_relaxed(
> > +                            1, &lrng_rb_reader);
> > +        unsigned int write_ptr =
> > +            (unsigned int)atomic_read(&lrng_rb_writer);
> > +
> > +        /*
> > +         * For boot time testing, only output one round of ring buffer.
> > +         */
> > +        if (boot_test && read_ptr > LRNG_TESTING_RINGBUFFER_SIZE) {
> > +            collected_data = -ENOMSG;
> > +            goto out;
> > +        }
> > +
> > +        /* We reached the writer */
> > +        if (!boot_test && ((write_ptr & LRNG_TESTING_RINGBUFFER_MASK) ==
> > +            (read_ptr & LRNG_TESTING_RINGBUFFER_MASK))) {
> > +
> 
> This is wrong. The fact that you haven’t reached the writer does not imply
> that you’re about to read valid data.

As I changed the code by using your locking suggestion. With that I think the 
code should now always read correct data. I will send an updated patch set 
tomorrow.

Thank you for your review.


[1] https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90B.pdf

[2] https://github.com/usnistgov/SP800-90B_EntropyAssessment

[3] http://www.chronox.de/lrng/lrng-tests-20191116.tar.xz - see the sp80090b 
directory for details

[4] http://www.chronox.de/lrng/doc/lrng.pdf

[5] https://www.bsi.bund.de/SharedDocs/Downloads/EN/BSI/Publications/Studies/
LinuxRNG/LinuxRNG_EN.pdf


Ciao
Stephan



^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v25 12/12] LRNG - add interface for gathering of raw entropy
  2019-11-17 22:55       ` Stephan Müller
@ 2019-11-19 10:04         ` Andy Lutomirski
  0 siblings, 0 replies; 162+ messages in thread
From: Andy Lutomirski @ 2019-11-19 10:04 UTC (permalink / raw)
  To: Stephan Müller
  Cc: Arnd Bergmann, Greg Kroah-Hartman, Linux Crypto Mailing List,
	LKML, Linux API, Eric W. Biederman, Alexander E. Patrakov,
	Ahmed S. Darwish, Theodore Y. Ts'o, Willy Tarreau,
	Matthew Garrett, Vito Caputo, Andreas Dilger, Jan Kara,
	Ray Strode, William Jon McCann, zhangjs, Andy Lutomirski,
	Florian Weimer, Lennart Poettering, Nicolai Stange, Peter,
	Matthias, Marcelo Henrique Cerri, Roman Drahtmueller,
	Neil Horman

On Sun, Nov 17, 2019 at 2:55 PM Stephan Müller <smueller@chronox.de> wrote:
>
> Am Samstag, 16. November 2019, 17:51:24 CET schrieb Andy Lutomirski:
>
> Hi Andy,
>
> > > On Nov 16, 2019, at 1:40 AM, Stephan Müller <smueller@chronox.de> wrote:
> > >
> > > The test interface allows a privileged process to capture the raw
> > > unconditioned noise that is collected by the LRNG for statistical
> > > analysis. Extracted noise data is not used to seed the LRNG. This
> > > is a test interface and not appropriate for production systems.
> > > Yet, the interface is considered to be sufficiently secured for
> > > production systems.
> > >
> > > Access to the data is given through the lrng_raw debugfs file. The
> > > data buffer should be multiples of sizeof(u32) to fill the entire
> > > buffer. Using the option lrng_testing.boot_test=1 the raw noise of
> > > the first 1000 entropy events since boot can be sampled.
> > >
> > > This test interface allows generating the data required for
> > > analysis whether the LRNG is in compliance with SP800-90B
> > > sections 3.1.3 and 3.1.4.
> > >
> > > CC: "Eric W. Biederman" <ebiederm@xmission.com>
> > > CC: "Alexander E. Patrakov" <patrakov@gmail.com>
> > > CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
> > > CC: "Theodore Y. Ts'o" <tytso@mit.edu>
> > > CC: Willy Tarreau <w@1wt.eu>
> > > CC: Matthew Garrett <mjg59@srcf.ucam.org>
> > > CC: Vito Caputo <vcaputo@pengaru.com>
> > > CC: Andreas Dilger <adilger.kernel@dilger.ca>
> > > CC: Jan Kara <jack@suse.cz>
> > > CC: Ray Strode <rstrode@redhat.com>
> > > CC: William Jon McCann <mccann@jhu.edu>
> > > CC: zhangjs <zachary@baishancloud.com>
> > > CC: Andy Lutomirski <luto@kernel.org>
> > > CC: Florian Weimer <fweimer@redhat.com>
> > > CC: Lennart Poettering <mzxreary@0pointer.de>
> > > CC: Nicolai Stange <nstange@suse.de>
> > > Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
> > > Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
> > > Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
> > > Tested-by: Neil Horman <nhorman@redhat.com>
> > > Signed-off-by: Stephan Mueller <smueller@chronox.de>
> > > ---
> > > drivers/char/lrng/Kconfig        |  16 ++
> > > drivers/char/lrng/Makefile       |   1 +
> > > drivers/char/lrng/lrng_testing.c | 324 +++++++++++++++++++++++++++++++
> > > 3 files changed, 341 insertions(+)
> > > create mode 100644 drivers/char/lrng/lrng_testing.c
> > >
> > > diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
> > > index e6ca3acc1e48..4ccc710832ef 100644
> > > --- a/drivers/char/lrng/Kconfig
> > > +++ b/drivers/char/lrng/Kconfig
> > > @@ -169,4 +169,20 @@ config LRNG_APT_CUTOFF
> > >
> > >    default 325 if !LRNG_APT_BROKEN
> > >    default 32 if LRNG_APT_BROKEN
> > >
> > > +config LRNG_TESTING
> > > +    bool "Enable entropy test interface to LRNG noise source"
> > > +    select CONFIG_DEBUG_FS
> > > +    help
> > > +      The test interface allows a privileged process to capture
> > > +      the raw unconditioned noise that is collected by the LRNG
> > > +      for statistical analysis. Extracted noise data is not used
> > > +      to seed the LRNG.
> > > +
> > > +      The raw noise data can be obtained using the lrng_raw
> > > +      debugfs file. Using the option lrng_testing.boot_test=1
> > > +      the raw noise of the first 1000 entropy events since boot
> > > +      can be sampled.
> > > +
> > > +      If unsure, say N.
> > > +
> > > endif # LRNG
> > > diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
> > > index 0713e9c0aa6e..c0b6cc4301fe 100644
> > > --- a/drivers/char/lrng/Makefile
> > > +++ b/drivers/char/lrng/Makefile
> > > @@ -16,3 +16,4 @@ obj-$(CONFIG_LRNG_KCAPI)    += lrng_kcapi.o
> > > obj-$(CONFIG_LRNG_JENT)        += lrng_jent.o
> > > obj-$(CONFIG_LRNG_TRNG_SUPPORT)    += lrng_trng.o
> > > obj-$(CONFIG_LRNG_HEALTH_TESTS)    += lrng_health.o
> > > +obj-$(CONFIG_LRNG_TESTING)    += lrng_testing.o
> > > diff --git a/drivers/char/lrng/lrng_testing.c
> > > b/drivers/char/lrng/lrng_testing.c new file mode 100644
> > > index 000000000000..5c33d3bd2172
> > > --- /dev/null
> > > +++ b/drivers/char/lrng/lrng_testing.c
> > > @@ -0,0 +1,324 @@
> > > +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
> > > +/*
> > > + * Linux Random Number Generator (LRNG) Raw entropy collection tool
> > > + *
> > > + * Copyright (C) 2019, Stephan Mueller <smueller@chronox.de>
> > > + */
> > > +
> > > +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> > > +
> > > +#include <linux/atomic.h>
> > > +#include <linux/bug.h>
> > > +#include <linux/debugfs.h>
> > > +#include <linux/module.h>
> > > +#include <linux/sched.h>
> > > +#include <linux/sched/signal.h>
> > > +#include <linux/slab.h>
> > > +#include <linux/string.h>
> > > +#include <linux/types.h>
> > > +#include <linux/uaccess.h>
> > > +#include <linux/workqueue.h>
> > > +#include <asm/errno.h>
> > > +
> > > +#include "lrng_internal.h"
> > > +
> > > +#define LRNG_TESTING_RINGBUFFER_SIZE    1024
> > > +#define LRNG_TESTING_RINGBUFFER_MASK    (LRNG_TESTING_RINGBUFFER_SIZE -
> > > 1)
> > > +
> > > +static u32 lrng_testing_rb[LRNG_TESTING_RINGBUFFER_SIZE];
> > > +static atomic_t lrng_rb_reader = ATOMIC_INIT(0);
> > > +static atomic_t lrng_rb_writer = ATOMIC_INIT(0);
> > > +static atomic_t lrng_rb_first_in = ATOMIC_INIT(0);
> > > +static atomic_t lrng_testing_enabled = ATOMIC_INIT(0);
> > > +
> > > +static DECLARE_WAIT_QUEUE_HEAD(lrng_raw_read_wait);
> > > +
> > > +static u32 boot_test = 0;
> > > +module_param(boot_test, uint, 0644);
> > > +MODULE_PARM_DESC(boot_test, "Enable gathering boot time entropy of the
> > > first" +                " entropy events");
> > > +
> > > +static inline void lrng_raw_entropy_reset(void)
> > > +{
> > > +    atomic_set(&lrng_rb_reader, 0);
> > > +    atomic_set(&lrng_rb_writer, 0);
> > > +    atomic_set(&lrng_rb_first_in, 0);
> > > +}
> > > +
> > > +static void lrng_raw_entropy_init(void)
> > > +{
> > > +    /*
> > > +     * The boot time testing implies we have a running test. If the
> > > +     * caller wants to clear it, he has to unset the boot_test flag
> > > +     * at runtime via sysfs to enable regular runtime testing
> > > +     */
> > > +    if (boot_test)
> > > +        return;
> > > +
> > > +    lrng_raw_entropy_reset();
> > > +    atomic_set(&lrng_testing_enabled, 1);
> > > +    pr_warn("Enabling raw entropy collection\n");
> > > +}
> > > +
> > > +static void lrng_raw_entropy_fini(void)
> > > +{
> > > +    if (boot_test)
> > > +        return;
> > > +
> > > +    lrng_raw_entropy_reset();
> > > +    atomic_set(&lrng_testing_enabled, 0);
> > > +    pr_warn("Disabling raw entropy collection\n");
> > > +}
> > > +
> > > +bool lrng_raw_entropy_store(u32 value)
> > > +{
> > > +    unsigned int write_ptr;
> > > +    unsigned int read_ptr;
> > > +
> > > +    if (!atomic_read(&lrng_testing_enabled) && !boot_test)
> > > +        return false;
> > > +
> > > +    write_ptr = (unsigned int)atomic_add_return_relaxed(1,
> > > &lrng_rb_writer); +    read_ptr = (unsigned
> > > int)atomic_read(&lrng_rb_reader);
>
> Before answering your comments, please allow me to clarify the following:
>
> This entire code is intended to obtain take raw unconditioned noise data that
> needs to be extracted from the kernel to user space to allow it to be further
> analyzed. This is also why it is mentioned in the Kconfig selection that in
> doubt one should select N and that this code is not intended for production
> kernels although this code should be secure enough to be present in production
> kernels.
>
> For example, raw unconditioned noise data needs to be processed by the
> complicated math outlined in chapter 6 of [1]. For that, there is a tool
> available, see [2]. For that tool, data is needed that is obtained with the
> getrawentropy tool available with [3] where this tool obtains the data from
> the SysFS file that is implemented with this C file.
>
> In addition, [1] even needs the data from the very first 1000 interrupts after
> boot. Hence, the LRNG needs to be able to store that data until user space can
> pick it up (see the boot_test variable).
>
> The assessment resulting from this can be reviewed at [4] section 3.2 In
> particular, the numbers provided at the end of sections 3.2.3 and 3.2.4 are
> obtained with this interface.
>
> Other examples where such raw unconditioned noise data is needed for further
> analysis is [5], especially chapter 6.
>
> This testing has nothing to do with the runtime testing provided with the
> patch set 11. All data that ends up here is not available to the LRNG and will
> not contribute to any entropy collection.
>
> See the following:
>
>


>         if (this_cpu_read(cpu_tlbstate.loaded_mm) == &init_mm)
>                 return;
>
> --
> 2.17.1
static inline void lrng_time_process(void)
> {
> ...
>         if (lrng_raw_entropy_store(now_time))
>                 return;
>
>
> bool lrng_raw_entropy_store(u32 value)
> {
> ...
>         if (!atomic_read(&lrng_testing_enabled) && !boot_test)
>                 return false;
> ...
>         return true;
>
> >
> > Am I correct in assuming that this function can be called concurrently in
> > different threads or CPUs?
>
> Yes, because it is called indirectly by add_interrupt_randomness.
> > > +
> > > +    /*
> > > +     * Disable entropy testing for boot time testing after ring buffer
> > > +     * is filled.
> > > +     */
> > > +    if (boot_test && write_ptr > LRNG_TESTING_RINGBUFFER_SIZE) {
> > > +        pr_warn_once("Boot time entropy collection test disabled\n");
> > > +        return false;
> > > +    }
> > > +
> > > +    if (boot_test && !atomic_read(&lrng_rb_first_in))
> > > +        pr_warn("Boot time entropy collection test enabled\n");
> > > +
> > > +    lrng_testing_rb[write_ptr & LRNG_TESTING_RINGBUFFER_MASK] = value;
> >
> > You’re writing *somewhere*, but not necessarily to the first open slot.
>
> The idea is that there is a reader pointer and a writer pointer where the
> reader always must be smaller or equal to the writer (modulo the size of the
> ring buffer). So, I do not care where the writer ptr is.
>
> All I need is that:
>
> 1. reader and writer ptr must start with the same value at boot time (e.g. 0)
>
> 2. reader ptr is always <= writer ptr in order for data to be read.

You're making an implicit assumption, though: that the writer has
actually written the data indicated by the writer ptr.  But you're
updating the writer ptr *before* you write, so that assumption is
false.

> But I simplified the code now, the code now only copies the data out if the
> reader <= writer modulo the ring buffer size. In this case, if the writer is
> much faster, then we loose some values.

I'll look at the new code.  I'm not sure what you mean by a <= b
modulo N -- in a cyclic group (e.g. the integers 0 .. N-1), there
isn't really a well-defined concept of <=.

^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v25 03/12] LRNG - /proc interface
  2019-11-17 12:16       ` Stephan Müller
@ 2019-11-19 10:06         ` Andy Lutomirski
  2019-11-19 10:55           ` Stephan Mueller
  0 siblings, 1 reply; 162+ messages in thread
From: Andy Lutomirski @ 2019-11-19 10:06 UTC (permalink / raw)
  To: Stephan Müller
  Cc: Arnd Bergmann, Greg Kroah-Hartman, Linux Crypto Mailing List,
	LKML, Linux API, Eric W. Biederman, Alexander E. Patrakov,
	Ahmed S. Darwish, Theodore Y. Ts'o, Willy Tarreau,
	Matthew Garrett, Vito Caputo, Andreas Dilger, Jan Kara,
	Ray Strode, William Jon McCann, zhangjs, Andy Lutomirski,
	Florian Weimer, Lennart Poettering, Nicolai Stange, Peter,
	Matthias, Marcelo Henrique Cerri, Roman Drahtmueller,
	Neil Horman

On Sun, Nov 17, 2019 at 4:16 AM Stephan Müller <smueller@chronox.de> wrote:
>
> Am Samstag, 16. November 2019, 17:39:40 CET schrieb Andy Lutomirski:
>
> Hi Andy,
>
> > > On Nov 16, 2019, at 1:40 AM, Stephan Müller <smueller@chronox.de> wrote:
> > >
> > > The LRNG /proc interface provides the same files as the legacy
> > > /dev/random. These files behave identically. Yet, all files are
> > > documented at [1].
> >
> > Why?
>
> I am not sure here: are you referring to the documentation? Or the one
> additional file?
>
> If it is the documentation, do you want me to add it to the patch description?
> I initially did not add it as these files were present and seemingly known
> what they provide. But I would add that documentation to the patch description
> if this is desired.

Sorry, I should have been a lot more explicit.  Why do you want to add
a new interface to read the RNG?  What's wrong with the old one?

I think your patch description should explain the purpose of the patch.

^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v25 10/12] LRNG - add TRNG support
  2019-11-17 11:10       ` Stephan Müller
@ 2019-11-19 10:07         ` Andy Lutomirski
  2019-11-19 10:46           ` Stephan Mueller
  2019-11-19 12:41           ` Greg Kroah-Hartman
  0 siblings, 2 replies; 162+ messages in thread
From: Andy Lutomirski @ 2019-11-19 10:07 UTC (permalink / raw)
  To: Stephan Müller
  Cc: Arnd Bergmann, Greg Kroah-Hartman, Linux Crypto Mailing List,
	LKML, Linux API, Eric W. Biederman, Alexander E. Patrakov,
	Ahmed S. Darwish, Theodore Y. Ts'o, Willy Tarreau,
	Matthew Garrett, Vito Caputo, Andreas Dilger, Jan Kara,
	Ray Strode, William Jon McCann, zhangjs, Andy Lutomirski,
	Florian Weimer, Lennart Poettering, Nicolai Stange, Peter,
	Matthias, Marcelo Henrique Cerri, Roman Drahtmueller,
	Neil Horman

On Sun, Nov 17, 2019 at 3:11 AM Stephan Müller <smueller@chronox.de> wrote:
>
> Am Samstag, 16. November 2019, 17:09:09 CET schrieb Andy Lutomirski:
>
> Hi Andy,
>
> > > On Nov 16, 2019, at 1:40 AM, Stephan Müller <smueller@chronox.de> wrote:
> > >
> > > The True Random Number Generator (TRNG) provides a random number
> > > generator with prediction resistance (SP800-90A terminology) or an NTG.1
> > > (AIS 31 terminology).
> >
> > ...
> >
> > > The secondary DRNGs seed from the TRNG if it is present. In addition,
> > > the /dev/random device accesses the TRNG.
> > >
> > > If the TRNG is disabled, the secondary DRNGs seed from the entropy pool
> > > and /dev/random behaves like getrandom(2).
> >
> > As mentioned before, I don’t like this API.  An application that, for some
> > reason, needs a TRNG, should have an API by which it either gets a TRNG or
> > an error. Similarly, an application that wants cryptographically secure
> > random numbers efficiently should have an API that does that.  With your
> > design, /dev/random tries to cater to both use cases, but one of the use
> > cases fails depending on kernel config.
> >
> > I think /dev/random should wait for enough entropy to initialize the system
> > but should not block after that. A TRNG should have an entirely new API
> > that is better than /dev/random.
>
> I apologize for the misunderstanding. I assumed we would introduce such /dev/
> true_random at a later stage.
>
> If you agree, I can certainly add /dev/true_random right now that links with
> the TRNG and make /dev/random behave as discussed, i.e. behave exactly like
> getrandom(..., 0);

Given that your series is already a decently large ABI change, I think
it would be polite to users to make all the anticipated changes all at
once to reduce the amount of churn everyone needs to deal with.

>
> As this would introduce a new device file now, is there a special process that
> I need to follow or do I need to copy? Which major/minor number should I use?
>
> Looking into static const struct memdev devlist[] I see
>
>          [8] = { "random", 0666, &random_fops, 0 },
>          [9] = { "urandom", 0666, &urandom_fops, 0 },
>
> Shall a true_random be added here with [10]?

I am not at all an expert on chardevs, but this sounds generally
reasonable.  gregkh is probably the real authority here.

^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v25 10/12] LRNG - add TRNG support
  2019-11-19 10:07         ` Andy Lutomirski
@ 2019-11-19 10:46           ` Stephan Mueller
  2019-11-19 12:41           ` Greg Kroah-Hartman
  1 sibling, 0 replies; 162+ messages in thread
From: Stephan Mueller @ 2019-11-19 10:46 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Arnd Bergmann, Greg Kroah-Hartman, Linux Crypto Mailing List,
	LKML, Linux API, Eric W. Biederman, Alexander E. Patrakov,
	Ahmed S. Darwish, Theodore Y. Ts'o, Willy Tarreau,
	Matthew Garrett, Vito Caputo, Andreas Dilger, Jan Kara,
	Ray Strode, William Jon McCann, zhangjs, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

Am Dienstag, 19. November 2019, 11:07:40 CET schrieb Andy Lutomirski:

Hi Andy,

> On Sun, Nov 17, 2019 at 3:11 AM Stephan Müller <smueller@chronox.de> wrote:
> > Am Samstag, 16. November 2019, 17:09:09 CET schrieb Andy Lutomirski:
> > 
> > Hi Andy,
> > 
> > > > On Nov 16, 2019, at 1:40 AM, Stephan Müller <smueller@chronox.de>
> > > > wrote:
> > > > 
> > > > The True Random Number Generator (TRNG) provides a random number
> > > > generator with prediction resistance (SP800-90A terminology) or an
> > > > NTG.1
> > > > (AIS 31 terminology).
> > > 
> > > ...
> > > 
> > > > The secondary DRNGs seed from the TRNG if it is present. In addition,
> > > > the /dev/random device accesses the TRNG.
> > > > 
> > > > If the TRNG is disabled, the secondary DRNGs seed from the entropy
> > > > pool
> > > > and /dev/random behaves like getrandom(2).
> > > 
> > > As mentioned before, I don’t like this API.  An application that, for
> > > some
> > > reason, needs a TRNG, should have an API by which it either gets a TRNG
> > > or
> > > an error. Similarly, an application that wants cryptographically secure
> > > random numbers efficiently should have an API that does that.  With your
> > > design, /dev/random tries to cater to both use cases, but one of the use
> > > cases fails depending on kernel config.
> > > 
> > > I think /dev/random should wait for enough entropy to initialize the
> > > system
> > > but should not block after that. A TRNG should have an entirely new API
> > > that is better than /dev/random.
> > 
> > I apologize for the misunderstanding. I assumed we would introduce such
> > /dev/ true_random at a later stage.
> > 
> > If you agree, I can certainly add /dev/true_random right now that links
> > with the TRNG and make /dev/random behave as discussed, i.e. behave
> > exactly like getrandom(..., 0);
> 
> Given that your series is already a decently large ABI change, I think
> it would be polite to users to make all the anticipated changes all at
> once to reduce the amount of churn everyone needs to deal with.

I fully agree with that. This is the reason for my question to ask for how to 
approach adding such additional interface for the TRNG. Considering that there 
are use cases for the blocking interfaces, I would like to have it present 
from the start.

That said, are you planning to keep the blocking_pool considering our 
discussion?

But may I ask why you say that there are ABI changes? The LRNG set tries to be 
100% API and ABI compliant to the existing random.c interfaces.

The only change is the runtime-behavior (e.g. time when something is seeded), 
performance of the interrupt handling and the kernel/user interfaces that may 
be noticeable by users. I.e. there are timing changes, but no technical 
changes.

The LRNG though would add one optional interface for kernel internal use and 
then the discussed /dev/true_random interface.
> 
> > As this would introduce a new device file now, is there a special process
> > that I need to follow or do I need to copy? Which major/minor number
> > should I use?
> > 
> > Looking into static const struct memdev devlist[] I see
> > 
> >          [8] = { "random", 0666, &random_fops, 0 },
> >          [9] = { "urandom", 0666, &urandom_fops, 0 },
> > 
> > Shall a true_random be added here with [10]?
> 
> I am not at all an expert on chardevs, but this sounds generally
> reasonable.  gregkh is probably the real authority here.

Thank you for the hint. Then I would like to wait for Greg on this.

Ciao
Stephan



^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v25 03/12] LRNG - /proc interface
  2019-11-19 10:06         ` Andy Lutomirski
@ 2019-11-19 10:55           ` Stephan Mueller
  2019-11-19 17:40             ` Andy Lutomirski
  0 siblings, 1 reply; 162+ messages in thread
From: Stephan Mueller @ 2019-11-19 10:55 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Arnd Bergmann, Greg Kroah-Hartman, Linux Crypto Mailing List,
	LKML, Linux API, Eric W. Biederman, Alexander E. Patrakov,
	Ahmed S. Darwish, Theodore Y. Ts'o, Willy Tarreau,
	Matthew Garrett, Vito Caputo, Andreas Dilger, Jan Kara,
	Ray Strode, William Jon McCann, zhangjs, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

Am Dienstag, 19. November 2019, 11:06:02 CET schrieb Andy Lutomirski:

Hi Andy,

> On Sun, Nov 17, 2019 at 4:16 AM Stephan Müller <smueller@chronox.de> wrote:
> > Am Samstag, 16. November 2019, 17:39:40 CET schrieb Andy Lutomirski:
> > 
> > Hi Andy,
> > 
> > > > On Nov 16, 2019, at 1:40 AM, Stephan Müller <smueller@chronox.de>
> > > > wrote:
> > > > 
> > > > The LRNG /proc interface provides the same files as the legacy
> > > > /dev/random. These files behave identically. Yet, all files are
> > > > documented at [1].
> > > 
> > > Why?
> > 
> > I am not sure here: are you referring to the documentation? Or the one
> > additional file?
> > 
> > If it is the documentation, do you want me to add it to the patch
> > description? I initially did not add it as these files were present and
> > seemingly known what they provide. But I would add that documentation to
> > the patch description if this is desired.
> 
> Sorry, I should have been a lot more explicit.  Why do you want to add
> a new interface to read the RNG?  What's wrong with the old one?

There is nothing wrong at all. I actually want to be 100% API and ABI 
compliant with the existing random.c. Thus, the list of the sysctls are 
identical to the existing random.c with the same behavior (hence I skipped the 
documentation of these files).

Yet, the wiring up of the interfaces to internal data structures and handlers 
is different than for the existing random.c.

Also, the reason why I created a separate lrng_proc.c (and lrng_interface.c) 
is to allow a possible merger of this similar code with the existing random.c. 
The only question that needs to be solved is to find a common way to invoke 
the random.c internal logic and the LRNG internal logic with these interfaces.
> 
> I think your patch description should explain the purpose of the patch.

Ok, I can surely add a description for each file to the patch description.

Ciao
Stephan



^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v25 10/12] LRNG - add TRNG support
  2019-11-19 10:07         ` Andy Lutomirski
  2019-11-19 10:46           ` Stephan Mueller
@ 2019-11-19 12:41           ` Greg Kroah-Hartman
  2019-11-20  8:58             ` Stephan Müller
  1 sibling, 1 reply; 162+ messages in thread
From: Greg Kroah-Hartman @ 2019-11-19 12:41 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Stephan Müller, Arnd Bergmann, Linux Crypto Mailing List,
	LKML, Linux API, Eric W. Biederman, Alexander E. Patrakov,
	Ahmed S. Darwish, Theodore Y. Ts'o, Willy Tarreau,
	Matthew Garrett, Vito Caputo, Andreas Dilger, Jan Kara,
	Ray Strode, William Jon McCann, zhangjs, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

On Tue, Nov 19, 2019 at 02:07:40AM -0800, Andy Lutomirski wrote:
> > As this would introduce a new device file now, is there a special process that
> > I need to follow or do I need to copy? Which major/minor number should I use?
> >
> > Looking into static const struct memdev devlist[] I see
> >
> >          [8] = { "random", 0666, &random_fops, 0 },
> >          [9] = { "urandom", 0666, &urandom_fops, 0 },
> >
> > Shall a true_random be added here with [10]?
> 
> I am not at all an expert on chardevs, but this sounds generally
> reasonable.  gregkh is probably the real authority here.

[10] is the aio char device node, so you better not try to overlap it or
bad things will happen :(

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v25 12/12] LRNG - add interface for gathering of raw entropy
  2019-11-16  9:38   ` [PATCH v25 12/12] LRNG - add interface for gathering of raw entropy Stephan Müller
  2019-11-16 16:51     ` Andy Lutomirski
@ 2019-11-19 17:17     ` Randy Dunlap
  2019-11-20  9:01       ` Stephan Müller
  2019-11-21 12:18     ` Nicolai Stange
  2 siblings, 1 reply; 162+ messages in thread
From: Randy Dunlap @ 2019-11-19 17:17 UTC (permalink / raw)
  To: Stephan Müller, Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

Hi,

On 11/16/19 1:38 AM, Stephan Müller wrote:
> diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
> index e6ca3acc1e48..4ccc710832ef 100644
> --- a/drivers/char/lrng/Kconfig
> +++ b/drivers/char/lrng/Kconfig
> @@ -169,4 +169,20 @@ config LRNG_APT_CUTOFF
>  	default 325 if !LRNG_APT_BROKEN
>  	default 32 if LRNG_APT_BROKEN
>  
> +config LRNG_TESTING
> +	bool "Enable entropy test interface to LRNG noise source"
> +	select CONFIG_DEBUG_FS

	That should be spelled as DEBUG_FS and preferably would be "depends on"
	instead of 'select'.


> +	help
> +	  The test interface allows a privileged process to capture
> +	  the raw unconditioned noise that is collected by the LRNG
> +	  for statistical analysis. Extracted noise data is not used
> +	  to seed the LRNG.
> +
> +	  The raw noise data can be obtained using the lrng_raw
> +	  debugfs file. Using the option lrng_testing.boot_test=1
> +	  the raw noise of the first 1000 entropy events since boot
> +	  can be sampled.
> +
> +	  If unsure, say N.
> +
>  endif # LRNG

thanks.
-- 
~Randy


^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v25 03/12] LRNG - /proc interface
  2019-11-19 10:55           ` Stephan Mueller
@ 2019-11-19 17:40             ` Andy Lutomirski
  0 siblings, 0 replies; 162+ messages in thread
From: Andy Lutomirski @ 2019-11-19 17:40 UTC (permalink / raw)
  To: Stephan Mueller
  Cc: Andy Lutomirski, Arnd Bergmann, Greg Kroah-Hartman,
	Linux Crypto Mailing List, LKML, Linux API, Eric W. Biederman,
	Alexander E. Patrakov, Ahmed S. Darwish, Theodore Y. Ts'o,
	Willy Tarreau, Matthew Garrett, Vito Caputo, Andreas Dilger,
	Jan Kara, Ray Strode, William Jon McCann, zhangjs,
	Florian Weimer, Lennart Poettering, Nicolai Stange, Peter,
	Matthias, Marcelo Henrique Cerri, Roman Drahtmueller,
	Neil Horman

On Tue, Nov 19, 2019 at 2:57 AM Stephan Mueller <smueller@chronox.de> wrote:
>
> Am Dienstag, 19. November 2019, 11:06:02 CET schrieb Andy Lutomirski:
>
> Hi Andy,
>
> > On Sun, Nov 17, 2019 at 4:16 AM Stephan Müller <smueller@chronox.de> wrote:
> > > Am Samstag, 16. November 2019, 17:39:40 CET schrieb Andy Lutomirski:
> > >
> > > Hi Andy,
> > >
> > > > > On Nov 16, 2019, at 1:40 AM, Stephan Müller <smueller@chronox.de>
> > > > > wrote:
> > > > >
> > > > > The LRNG /proc interface provides the same files as the legacy
> > > > > /dev/random. These files behave identically. Yet, all files are
> > > > > documented at [1].
> > > >
> > > > Why?
> > >
> > > I am not sure here: are you referring to the documentation? Or the one
> > > additional file?
> > >
> > > If it is the documentation, do you want me to add it to the patch
> > > description? I initially did not add it as these files were present and
> > > seemingly known what they provide. But I would add that documentation to
> > > the patch description if this is desired.
> >
> > Sorry, I should have been a lot more explicit.  Why do you want to add
> > a new interface to read the RNG?  What's wrong with the old one?
>
> There is nothing wrong at all. I actually want to be 100% API and ABI
> compliant with the existing random.c. Thus, the list of the sysctls are
> identical to the existing random.c with the same behavior (hence I skipped the
> documentation of these files).

Whoops, I misunderstood your commit message.  You said "The LRNG /proc
interface provides the same files as the legacy
/dev/random.".  I assumed that meant that you had a file in /proc that
worked like /dev/random.

So never mind.

^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v25 10/12] LRNG - add TRNG support
  2019-11-19 12:41           ` Greg Kroah-Hartman
@ 2019-11-20  8:58             ` Stephan Müller
  2019-11-20  9:55               ` Alexander E. Patrakov
  2019-11-20 13:29               ` Greg Kroah-Hartman
  0 siblings, 2 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-20  8:58 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Andy Lutomirski, Arnd Bergmann, Linux Crypto Mailing List, LKML,
	Linux API, Eric W. Biederman, Alexander E. Patrakov,
	Ahmed S. Darwish, Theodore Y. Ts'o, Willy Tarreau,
	Matthew Garrett, Vito Caputo, Andreas Dilger, Jan Kara,
	Ray Strode, William Jon McCann, zhangjs, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

Am Dienstag, 19. November 2019, 13:41:50 CET schrieb Greg Kroah-Hartman:

Hi Greg,

> On Tue, Nov 19, 2019 at 02:07:40AM -0800, Andy Lutomirski wrote:
> > > As this would introduce a new device file now, is there a special
> > > process that I need to follow or do I need to copy? Which major/minor
> > > number should I use?
> > > 
> > > Looking into static const struct memdev devlist[] I see
> > > 
> > >          [8] = { "random", 0666, &random_fops, 0 },
> > >          [9] = { "urandom", 0666, &urandom_fops, 0 },
> > > 
> > > Shall a true_random be added here with [10]?
> > 
> > I am not at all an expert on chardevs, but this sounds generally
> > reasonable.  gregkh is probably the real authority here.
> 
> [10] is the aio char device node, so you better not try to overlap it or
> bad things will happen :(

Thanks for your insights.

Which device minor number could we use?

Or another idea and apologies if I restart this conversation as there was 
already a discussion around it: what about extending the getrandom(2) call 
instead of adding a device file?

What about adding yet another flag to getrandom: GRND_TRUERANDOM and process 
it as follows:

        if (flags & ~(GRND_NONBLOCK|GRND_RANDOM|GRND_INSECURE|
GRND_TRUERANDOM))
                return -EINVAL;

        //From Andy's tree
        /*
         * Requesting insecure and blocking randomness at the same time makes
         * no sense.
         */
        if ((flags & (GRND_INSECURE|GRND_RANDOM)) == (GRND_INSECURE|
GRND_RANDOM))
                return -EINVAL;

	  /* We only allow GRND_TRUERANDOM by itself or with NONBLOCK */
	  if (! ((flags & GRND_TRUERANDOM) &&
               ((flags == GRND_TRUERANDOM) ||
                (flags == GRND_TRUERANDOM | GRND_NONBLOCK))))
		return -EINVAL;

	if (flags & GRND_TRUERANDOM) {
		... do the TRNG processing ...
		... may return -ENOPNOTSUPP if no TRNG available ...
	}

Thanks a lot.


Ciao
Stephan



^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v25 12/12] LRNG - add interface for gathering of raw entropy
  2019-11-19 17:17     ` Randy Dunlap
@ 2019-11-20  9:01       ` Stephan Müller
  0 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-20  9:01 UTC (permalink / raw)
  To: Randy Dunlap
  Cc: Arnd Bergmann, Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

Am Dienstag, 19. November 2019, 18:17:55 CET schrieb Randy Dunlap:

Hi Randy,

> Hi,
> 
> On 11/16/19 1:38 AM, Stephan Müller wrote:
> > diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
> > index e6ca3acc1e48..4ccc710832ef 100644
> > --- a/drivers/char/lrng/Kconfig
> > +++ b/drivers/char/lrng/Kconfig
> > @@ -169,4 +169,20 @@ config LRNG_APT_CUTOFF
> > 
> >  	default 325 if !LRNG_APT_BROKEN
> >  	default 32 if LRNG_APT_BROKEN
> > 
> > +config LRNG_TESTING
> > +	bool "Enable entropy test interface to LRNG noise source"
> > +	select CONFIG_DEBUG_FS
> 
> 	That should be spelled as DEBUG_FS and preferably would be "depends on"
> 	instead of 'select'.

Fixed.

Thank you very much.

Ciao
Stephan



^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v25 10/12] LRNG - add TRNG support
  2019-11-20  8:58             ` Stephan Müller
@ 2019-11-20  9:55               ` Alexander E. Patrakov
  2019-11-20 13:29               ` Greg Kroah-Hartman
  1 sibling, 0 replies; 162+ messages in thread
From: Alexander E. Patrakov @ 2019-11-20  9:55 UTC (permalink / raw)
  To: Stephan Müller, Greg Kroah-Hartman
  Cc: Andy Lutomirski, Arnd Bergmann, Linux Crypto Mailing List, LKML,
	Linux API, Eric W. Biederman, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Florian Weimer, Lennart Poettering,
	Nicolai Stange, Peter, Matthias, Marcelo Henrique Cerri,
	Roman Drahtmueller, Neil Horman

20.11.2019 13:58, Stephan Müller пишет:

> Or another idea and apologies if I restart this conversation as there was
> already a discussion around it: what about extending the getrandom(2) call
> instead of adding a device file?
> 
> What about adding yet another flag to getrandom: GRND_TRUERANDOM and process
> it as follows:
> 
>          if (flags & ~(GRND_NONBLOCK|GRND_RANDOM|GRND_INSECURE|
> GRND_TRUERANDOM))
>                  return -EINVAL;
> 
>          //From Andy's tree
>          /*
>           * Requesting insecure and blocking randomness at the same time makes
>           * no sense.
>           */
>          if ((flags & (GRND_INSECURE|GRND_RANDOM)) == (GRND_INSECURE|
> GRND_RANDOM))
>                  return -EINVAL;
> 
> 	  /* We only allow GRND_TRUERANDOM by itself or with NONBLOCK */
> 	  if (! ((flags & GRND_TRUERANDOM) &&
>                 ((flags == GRND_TRUERANDOM) ||
>                  (flags == GRND_TRUERANDOM | GRND_NONBLOCK))))
> 		return -EINVAL;
> 
> 	if (flags & GRND_TRUERANDOM) {
> 		... do the TRNG processing ...
> 		... may return -ENOPNOTSUPP if no TRNG available ...
> 	}

This would totally miss the point of adding a device node: UNIX 
permissions that don't allow "others" to read and deplete "true" random 
numbers.

-- 
Alexander E. Patrakov

^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v25 10/12] LRNG - add TRNG support
  2019-11-20  8:58             ` Stephan Müller
  2019-11-20  9:55               ` Alexander E. Patrakov
@ 2019-11-20 13:29               ` Greg Kroah-Hartman
  2019-11-20 19:51                 ` Stephan Müller
  1 sibling, 1 reply; 162+ messages in thread
From: Greg Kroah-Hartman @ 2019-11-20 13:29 UTC (permalink / raw)
  To: Stephan Müller
  Cc: Andy Lutomirski, Arnd Bergmann, Linux Crypto Mailing List, LKML,
	Linux API, Eric W. Biederman, Alexander E. Patrakov,
	Ahmed S. Darwish, Theodore Y. Ts'o, Willy Tarreau,
	Matthew Garrett, Vito Caputo, Andreas Dilger, Jan Kara,
	Ray Strode, William Jon McCann, zhangjs, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

On Wed, Nov 20, 2019 at 09:58:35AM +0100, Stephan Müller wrote:
> Am Dienstag, 19. November 2019, 13:41:50 CET schrieb Greg Kroah-Hartman:
> 
> Hi Greg,
> 
> > On Tue, Nov 19, 2019 at 02:07:40AM -0800, Andy Lutomirski wrote:
> > > > As this would introduce a new device file now, is there a special
> > > > process that I need to follow or do I need to copy? Which major/minor
> > > > number should I use?
> > > > 
> > > > Looking into static const struct memdev devlist[] I see
> > > > 
> > > >          [8] = { "random", 0666, &random_fops, 0 },
> > > >          [9] = { "urandom", 0666, &urandom_fops, 0 },
> > > > 
> > > > Shall a true_random be added here with [10]?
> > > 
> > > I am not at all an expert on chardevs, but this sounds generally
> > > reasonable.  gregkh is probably the real authority here.
> > 
> > [10] is the aio char device node, so you better not try to overlap it or
> > bad things will happen :(
> 
> Thanks for your insights.
> 
> Which device minor number could we use?

Get your own dynamic one by using a misc device if you _REALLY_ want to
add yet-another-char-node-for-random-data.

But I would have thought that we all realize that this is not the way to
do things.  Let's not have "random", "urandom", and "true_random" be
something we want to totally confuse userspace with, that way is insane.

Please just make the existing userspace api "just work", don't add to
the mess.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v25 09/12] LRNG - add Jitter RNG fast noise source
  2019-11-16  9:36   ` [PATCH v25 09/12] LRNG - add Jitter RNG fast noise source Stephan Müller
@ 2019-11-20 13:33     ` Neil Horman
  2019-11-20 20:07       ` Stephan Müller
  0 siblings, 1 reply; 162+ messages in thread
From: Neil Horman @ 2019-11-20 13:33 UTC (permalink / raw)
  To: Stephan Müller
  Cc: Arnd Bergmann, Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller

On Sat, Nov 16, 2019 at 10:36:52AM +0100, Stephan Müller wrote:
> The Jitter RNG fast noise source implemented as part of the kernel
> crypto API is queried for 256 bits of entropy at the time the seed
> buffer managed by the LRNG is about to be filled.
> 
> CC: "Eric W. Biederman" <ebiederm@xmission.com>
> CC: "Alexander E. Patrakov" <patrakov@gmail.com>
> CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
> CC: "Theodore Y. Ts'o" <tytso@mit.edu>
> CC: Willy Tarreau <w@1wt.eu>
> CC: Matthew Garrett <mjg59@srcf.ucam.org>
> CC: Vito Caputo <vcaputo@pengaru.com>
> CC: Andreas Dilger <adilger.kernel@dilger.ca>
> CC: Jan Kara <jack@suse.cz>
> CC: Ray Strode <rstrode@redhat.com>
> CC: William Jon McCann <mccann@jhu.edu>
> CC: zhangjs <zachary@baishancloud.com>
> CC: Andy Lutomirski <luto@kernel.org>
> CC: Florian Weimer <fweimer@redhat.com>
> CC: Lennart Poettering <mzxreary@0pointer.de>
> CC: Nicolai Stange <nstange@suse.de>
> Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
> Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
> Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
> Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
> Tested-by: Neil Horman <nhorman@redhat.com>
> Signed-off-by: Stephan Mueller <smueller@chronox.de>
> ---
>  drivers/char/lrng/Kconfig     | 11 +++++
>  drivers/char/lrng/Makefile    |  1 +
>  drivers/char/lrng/lrng_jent.c | 88 +++++++++++++++++++++++++++++++++++
>  3 files changed, 100 insertions(+)
>  create mode 100644 drivers/char/lrng/lrng_jent.c
> 
> diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
> index 03e6e2ec356b..80fc723c67d2 100644
> --- a/drivers/char/lrng/Kconfig
> +++ b/drivers/char/lrng/Kconfig
> @@ -80,4 +80,15 @@ config LRNG_KCAPI
>  	  provided by the selected kernel crypto API RNG.
>  endif # LRNG_DRNG_SWITCH
>  
> +config LRNG_JENT
> +	bool "Enable Jitter RNG as LRNG Seed Source"
> +	select CRYPTO_JITTERENTROPY
> +	help
> +	  The Linux RNG may use the Jitter RNG as noise source. Enabling
> +	  this option enables the use of the Jitter RNG. Its default
> +	  entropy level is 16 bits of entropy per 256 data bits delivered
> +	  by the Jitter RNG. This entropy level can be changed at boot
> +	  time or at runtime with the lrng_base.jitterrng configuration
> +	  variable.
> +
>  endif # LRNG
> diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
> index 027b6ea51c20..a87d800c9aae 100644
> --- a/drivers/char/lrng/Makefile
> +++ b/drivers/char/lrng/Makefile
> @@ -13,3 +13,4 @@ obj-$(CONFIG_SYSCTL)		+= lrng_proc.o
>  obj-$(CONFIG_LRNG_DRNG_SWITCH)	+= lrng_switch.o
>  obj-$(CONFIG_LRNG_DRBG)		+= lrng_drbg.o
>  obj-$(CONFIG_LRNG_KCAPI)	+= lrng_kcapi.o
> +obj-$(CONFIG_LRNG_JENT)		+= lrng_jent.o
> diff --git a/drivers/char/lrng/lrng_jent.c b/drivers/char/lrng/lrng_jent.c
> new file mode 100644
> index 000000000000..43114a44b8f5
> --- /dev/null
> +++ b/drivers/char/lrng/lrng_jent.c
> @@ -0,0 +1,88 @@
> +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
> +/*
> + * LRNG Fast Noise Source: Jitter RNG
> + *
> + * Copyright (C) 2016 - 2019, Stephan Mueller <smueller@chronox.de>
> + */
> +
> +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> +
> +#include "lrng_internal.h"
> +
> +/*
> + * Estimated entropy of data is a 16th of LRNG_DRNG_SECURITY_STRENGTH_BITS.
> + * Albeit a full entropy assessment is provided for the noise source indicating
> + * that it provides high entropy rates and considering that it deactivates
> + * when it detects insufficient hardware, the chosen under estimation of
> + * entropy is considered to be acceptable to all reviewers.
> + */
> +static u32 jitterrng = LRNG_DRNG_SECURITY_STRENGTH_BITS>>4;
> +module_param(jitterrng, uint, 0644);
> +MODULE_PARM_DESC(jitterrng, "Entropy in bits of 256 data bits from Jitter "
> +			    "RNG noise source");
> +
> +/**
> + * Get Jitter RNG entropy
> + *
> + * @outbuf buffer to store entropy
> + * @outbuflen length of buffer
> + * @return > 0 on success where value provides the added entropy in bits
> + *	   0 if no fast source was available
> + */
> +struct rand_data;
> +struct rand_data *jent_lrng_entropy_collector(void);
> +int jent_read_entropy(struct rand_data *ec, unsigned char *data,
> +		      unsigned int len);
> +static struct rand_data *lrng_jent_state;
> +
> +u32 lrng_get_jent(u8 *outbuf, unsigned int outbuflen)
> +{
> +	int ret;
> +	u32 ent_bits = jitterrng;
> +	unsigned long flags;
> +	static DEFINE_SPINLOCK(lrng_jent_lock);
> +	static int lrng_jent_initialized = 0;
> +
> +	spin_lock_irqsave(&lrng_jent_lock, flags);
> +
> +	if (!ent_bits || (lrng_jent_initialized == -1)) {
> +		spin_unlock_irqrestore(&lrng_jent_lock, flags);
> +		return 0;
> +	}
> +
this works, but I think you can avoid the use of the spin lock on the read calls
here.  If you assign a global pointer to the value of &lrng_jent_state on init,
you can just take the spinlock on assignment, and assume its stable after that
(which it should be given that its only ever going to point to a static data
structure).

Neil

> +	if (!lrng_jent_initialized) {
> +		lrng_jent_state = jent_lrng_entropy_collector();
> +		if (!lrng_jent_state) {
> +			jitterrng = 0;
> +			lrng_jent_initialized = -1;
> +			spin_unlock_irqrestore(&lrng_jent_lock, flags);
> +			pr_info("Jitter RNG unusable on current system\n");
> +			return 0;
> +		}
> +		lrng_jent_initialized = 1;
> +		pr_debug("Jitter RNG working on current system\n");
> +	}
> +	ret = jent_read_entropy(lrng_jent_state, outbuf, outbuflen);
> +	spin_unlock_irqrestore(&lrng_jent_lock, flags);
> +
> +	if (ret) {
> +		pr_debug("Jitter RNG failed with %d\n", ret);
> +		return 0;
> +	}
> +
> +	/* Obtain entropy statement */
> +	if (outbuflen != LRNG_DRNG_SECURITY_STRENGTH_BYTES)
> +		ent_bits = (ent_bits * outbuflen<<3) /
> +			   LRNG_DRNG_SECURITY_STRENGTH_BITS;
> +	/* Cap entropy to buffer size in bits */
> +	ent_bits = min_t(u32, ent_bits, outbuflen<<3);
> +	pr_debug("obtained %u bits of entropy from Jitter RNG noise source\n",
> +		 ent_bits);
> +
> +	return ent_bits;
> +}
> +
> +u32 lrng_jent_entropylevel(void)
> +{
> +	return min_t(u32, jitterrng, LRNG_DRNG_SECURITY_STRENGTH_BITS);
> +}
> -- 
> 2.23.0
> 
> 
> 
> 


^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v25 10/12] LRNG - add TRNG support
  2019-11-20 13:29               ` Greg Kroah-Hartman
@ 2019-11-20 19:51                 ` Stephan Müller
  2019-11-20 19:57                   ` Alexander E. Patrakov
  2019-11-20 20:32                   ` Greg Kroah-Hartman
  0 siblings, 2 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-20 19:51 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Andy Lutomirski, Arnd Bergmann, Linux Crypto Mailing List, LKML,
	Linux API, Eric W. Biederman, Alexander E. Patrakov,
	Ahmed S. Darwish, Theodore Y. Ts'o, Willy Tarreau,
	Matthew Garrett, Vito Caputo, Andreas Dilger, Jan Kara,
	Ray Strode, William Jon McCann, zhangjs, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

Am Mittwoch, 20. November 2019, 14:29:18 CET schrieb Greg Kroah-Hartman:

Hi Greg,

> On Wed, Nov 20, 2019 at 09:58:35AM +0100, Stephan Müller wrote:
> > Am Dienstag, 19. November 2019, 13:41:50 CET schrieb Greg Kroah-Hartman:
> > 
> > Hi Greg,
> > 
> > > On Tue, Nov 19, 2019 at 02:07:40AM -0800, Andy Lutomirski wrote:
> > > > > As this would introduce a new device file now, is there a special
> > > > > process that I need to follow or do I need to copy? Which
> > > > > major/minor
> > > > > number should I use?
> > > > > 
> > > > > Looking into static const struct memdev devlist[] I see
> > > > > 
> > > > >          [8] = { "random", 0666, &random_fops, 0 },
> > > > >          [9] = { "urandom", 0666, &urandom_fops, 0 },
> > > > > 
> > > > > Shall a true_random be added here with [10]?
> > > > 
> > > > I am not at all an expert on chardevs, but this sounds generally
> > > > reasonable.  gregkh is probably the real authority here.
> > > 
> > > [10] is the aio char device node, so you better not try to overlap it or
> > > bad things will happen :(
> > 
> > Thanks for your insights.
> > 
> > Which device minor number could we use?
> 
> Get your own dynamic one by using a misc device if you _REALLY_ want to
> add yet-another-char-node-for-random-data.
> 
> But I would have thought that we all realize that this is not the way to
> do things.  Let's not have "random", "urandom", and "true_random" be
> something we want to totally confuse userspace with, that way is insane.
> 
> Please just make the existing userspace api "just work", don't add to
> the mess.

Thank you, I think we should follow that advise.

With that and considering Alexander's rightful remark we have a challenge. So, 
changing the syscall may not be the right way unless we find a way to restrict 
the permissions somehow (capability? LSM? None of that seems to be a good 
fit).

What about providing a /sys file? I.e. adding a file that:

a) has permissions 440 per default and maybe the ownership of root:root

b) allow user space to perform a chown/chgrp

c) only supports reading of data from user space

But then, how could we provide a common interface for the existing random.c 
and the LRNG?

Or should we use a proc file for that? If yes, I guess it should not be a 
sysctl, but a "regular" proc file that should allow a chown(2) operation. On 
the other hand, is proc the right place to provide a user space interface for 
exporting data to user?

Thanks a lot.

Ciao
Stephan



^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v25 10/12] LRNG - add TRNG support
  2019-11-20 19:51                 ` Stephan Müller
@ 2019-11-20 19:57                   ` Alexander E. Patrakov
  2019-11-20 20:32                   ` Greg Kroah-Hartman
  1 sibling, 0 replies; 162+ messages in thread
From: Alexander E. Patrakov @ 2019-11-20 19:57 UTC (permalink / raw)
  To: Stephan Müller, Greg Kroah-Hartman
  Cc: Andy Lutomirski, Arnd Bergmann, Linux Crypto Mailing List, LKML,
	Linux API, Eric W. Biederman, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Florian Weimer, Lennart Poettering,
	Nicolai Stange, Peter, Matthias, Marcelo Henrique Cerri,
	Roman Drahtmueller, Neil Horman

[-- Attachment #1: Type: text/plain, Size: 2952 bytes --]

21.11.2019 00:51, Stephan Müller пишет:
> Am Mittwoch, 20. November 2019, 14:29:18 CET schrieb Greg Kroah-Hartman:
> 
> Hi Greg,
> 
>> On Wed, Nov 20, 2019 at 09:58:35AM +0100, Stephan Müller wrote:
>>> Am Dienstag, 19. November 2019, 13:41:50 CET schrieb Greg Kroah-Hartman:
>>>
>>> Hi Greg,
>>>
>>>> On Tue, Nov 19, 2019 at 02:07:40AM -0800, Andy Lutomirski wrote:
>>>>>> As this would introduce a new device file now, is there a special
>>>>>> process that I need to follow or do I need to copy? Which
>>>>>> major/minor
>>>>>> number should I use?
>>>>>>
>>>>>> Looking into static const struct memdev devlist[] I see
>>>>>>
>>>>>>           [8] = { "random", 0666, &random_fops, 0 },
>>>>>>           [9] = { "urandom", 0666, &urandom_fops, 0 },
>>>>>>
>>>>>> Shall a true_random be added here with [10]?
>>>>>
>>>>> I am not at all an expert on chardevs, but this sounds generally
>>>>> reasonable.  gregkh is probably the real authority here.
>>>>
>>>> [10] is the aio char device node, so you better not try to overlap it or
>>>> bad things will happen :(
>>>
>>> Thanks for your insights.
>>>
>>> Which device minor number could we use?
>>
>> Get your own dynamic one by using a misc device if you _REALLY_ want to
>> add yet-another-char-node-for-random-data.
>>
>> But I would have thought that we all realize that this is not the way to
>> do things.  Let's not have "random", "urandom", and "true_random" be
>> something we want to totally confuse userspace with, that way is insane.
>>
>> Please just make the existing userspace api "just work", don't add to
>> the mess.
> 
> Thank you, I think we should follow that advise.
> 
> With that and considering Alexander's rightful remark we have a challenge. So,
> changing the syscall may not be the right way unless we find a way to restrict
> the permissions somehow (capability? LSM? None of that seems to be a good
> fit).
> 
> What about providing a /sys file? I.e. adding a file that:
> 
> a) has permissions 440 per default and maybe the ownership of root:root
> 
> b) allow user space to perform a chown/chgrp
> 
> c) only supports reading of data from user space
> 
> But then, how could we provide a common interface for the existing random.c
> and the LRNG?
> 
> Or should we use a proc file for that? If yes, I guess it should not be a
> sysctl, but a "regular" proc file that should allow a chown(2) operation. On
> the other hand, is proc the right place to provide a user space interface for
> exporting data to user?
> 
> Thanks a lot.
> 
> Ciao
> Stephan
> 
> 

I'd say that a sys or proc file is worse than a device node, because the 
wanted semantics are exactly those of a device node. Besides, a chown of 
a sysfs file is something not friendly to containers. We may need 
different uids in different containers to be able to access true random 
data.

-- 
Alexander E. Patrakov


[-- Attachment #2: Криптографическая подпись S/MIME --]
[-- Type: application/pkcs7-signature, Size: 4052 bytes --]

^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v25 09/12] LRNG - add Jitter RNG fast noise source
  2019-11-20 13:33     ` Neil Horman
@ 2019-11-20 20:07       ` Stephan Müller
  2019-11-21 14:19         ` Neil Horman
  0 siblings, 1 reply; 162+ messages in thread
From: Stephan Müller @ 2019-11-20 20:07 UTC (permalink / raw)
  To: Neil Horman
  Cc: Arnd Bergmann, Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller

Am Mittwoch, 20. November 2019, 14:33:03 CET schrieb Neil Horman:

Hi Neil,

> On Sat, Nov 16, 2019 at 10:36:52AM +0100, Stephan Müller wrote:
> > The Jitter RNG fast noise source implemented as part of the kernel
> > crypto API is queried for 256 bits of entropy at the time the seed
> > buffer managed by the LRNG is about to be filled.
> > 
> > CC: "Eric W. Biederman" <ebiederm@xmission.com>
> > CC: "Alexander E. Patrakov" <patrakov@gmail.com>
> > CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
> > CC: "Theodore Y. Ts'o" <tytso@mit.edu>
> > CC: Willy Tarreau <w@1wt.eu>
> > CC: Matthew Garrett <mjg59@srcf.ucam.org>
> > CC: Vito Caputo <vcaputo@pengaru.com>
> > CC: Andreas Dilger <adilger.kernel@dilger.ca>
> > CC: Jan Kara <jack@suse.cz>
> > CC: Ray Strode <rstrode@redhat.com>
> > CC: William Jon McCann <mccann@jhu.edu>
> > CC: zhangjs <zachary@baishancloud.com>
> > CC: Andy Lutomirski <luto@kernel.org>
> > CC: Florian Weimer <fweimer@redhat.com>
> > CC: Lennart Poettering <mzxreary@0pointer.de>
> > CC: Nicolai Stange <nstange@suse.de>
> > Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
> > Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
> > Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
> > Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
> > Tested-by: Neil Horman <nhorman@redhat.com>
> > Signed-off-by: Stephan Mueller <smueller@chronox.de>
> > ---
> > 
> >  drivers/char/lrng/Kconfig     | 11 +++++
> >  drivers/char/lrng/Makefile    |  1 +
> >  drivers/char/lrng/lrng_jent.c | 88 +++++++++++++++++++++++++++++++++++
> >  3 files changed, 100 insertions(+)
> >  create mode 100644 drivers/char/lrng/lrng_jent.c
> > 
> > diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
> > index 03e6e2ec356b..80fc723c67d2 100644
> > --- a/drivers/char/lrng/Kconfig
> > +++ b/drivers/char/lrng/Kconfig
> > @@ -80,4 +80,15 @@ config LRNG_KCAPI
> > 
> >  	  provided by the selected kernel crypto API RNG.
> >  
> >  endif # LRNG_DRNG_SWITCH
> > 
> > +config LRNG_JENT
> > +	bool "Enable Jitter RNG as LRNG Seed Source"
> > +	select CRYPTO_JITTERENTROPY
> > +	help
> > +	  The Linux RNG may use the Jitter RNG as noise source. Enabling
> > +	  this option enables the use of the Jitter RNG. Its default
> > +	  entropy level is 16 bits of entropy per 256 data bits delivered
> > +	  by the Jitter RNG. This entropy level can be changed at boot
> > +	  time or at runtime with the lrng_base.jitterrng configuration
> > +	  variable.
> > +
> > 
> >  endif # LRNG
> > 
> > diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
> > index 027b6ea51c20..a87d800c9aae 100644
> > --- a/drivers/char/lrng/Makefile
> > +++ b/drivers/char/lrng/Makefile
> > @@ -13,3 +13,4 @@ obj-$(CONFIG_SYSCTL)		+= lrng_proc.o
> > 
> >  obj-$(CONFIG_LRNG_DRNG_SWITCH)	+= lrng_switch.o
> >  obj-$(CONFIG_LRNG_DRBG)		+= lrng_drbg.o
> >  obj-$(CONFIG_LRNG_KCAPI)	+= lrng_kcapi.o
> > 
> > +obj-$(CONFIG_LRNG_JENT)		+= lrng_jent.o
> > diff --git a/drivers/char/lrng/lrng_jent.c b/drivers/char/lrng/lrng_jent.c
> > new file mode 100644
> > index 000000000000..43114a44b8f5
> > --- /dev/null
> > +++ b/drivers/char/lrng/lrng_jent.c
> > @@ -0,0 +1,88 @@
> > +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
> > +/*
> > + * LRNG Fast Noise Source: Jitter RNG
> > + *
> > + * Copyright (C) 2016 - 2019, Stephan Mueller <smueller@chronox.de>
> > + */
> > +
> > +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> > +
> > +#include "lrng_internal.h"
> > +
> > +/*
> > + * Estimated entropy of data is a 16th of
> > LRNG_DRNG_SECURITY_STRENGTH_BITS. + * Albeit a full entropy assessment is
> > provided for the noise source indicating + * that it provides high
> > entropy rates and considering that it deactivates + * when it detects
> > insufficient hardware, the chosen under estimation of + * entropy is
> > considered to be acceptable to all reviewers.
> > + */
> > +static u32 jitterrng = LRNG_DRNG_SECURITY_STRENGTH_BITS>>4;
> > +module_param(jitterrng, uint, 0644);
> > +MODULE_PARM_DESC(jitterrng, "Entropy in bits of 256 data bits from Jitter
> > " +			    "RNG noise source");
> > +
> > +/**
> > + * Get Jitter RNG entropy
> > + *
> > + * @outbuf buffer to store entropy
> > + * @outbuflen length of buffer
> > + * @return > 0 on success where value provides the added entropy in bits
> > + *	   0 if no fast source was available
> > + */
> > +struct rand_data;
> > +struct rand_data *jent_lrng_entropy_collector(void);
> > +int jent_read_entropy(struct rand_data *ec, unsigned char *data,
> > +		      unsigned int len);
> > +static struct rand_data *lrng_jent_state;
> > +
> > +u32 lrng_get_jent(u8 *outbuf, unsigned int outbuflen)
> > +{
> > +	int ret;
> > +	u32 ent_bits = jitterrng;
> > +	unsigned long flags;
> > +	static DEFINE_SPINLOCK(lrng_jent_lock);
> > +	static int lrng_jent_initialized = 0;
> > +
> > +	spin_lock_irqsave(&lrng_jent_lock, flags);
> > +
> > +	if (!ent_bits || (lrng_jent_initialized == -1)) {
> > +		spin_unlock_irqrestore(&lrng_jent_lock, flags);
> > +		return 0;
> > +	}
> > +
> 
> this works, but I think you can avoid the use of the spin lock on the read
> calls here.  If you assign a global pointer to the value of
> &lrng_jent_state on init, you can just take the spinlock on assignment, and
> assume its stable after that (which it should be given that its only ever
> going to point to a static data structure).

It is correct that the lock protects the assignment of the data structure.

But the Jitter RNG itself is not multi-threaded. So, a form of serialization 
is needed to also "read" data from the Jitter RNG using one and the same 
state.

Granted, there is a serialization in the current code as the 
lrng_pool_trylock() is taken before the Jitter RNG is called by 
lrng_fill_seed_buffer which effectively serializes all requests to also the 
Jitter RNG. But this is coincidence in this case. I would think, however, that 
this coincidence could easily lead to programming errors further down the road 
when the spinlock is not present and that trylock() is moved to some place 
else considering that this trylock() is meant to protect reading the entropy 
pool and not the Jitter RNG.

As the reading of the Jitter RNG is always performed in process context, I 
think having this additional spin lock against possible programming errors 
should not lead to performance regressions.

What do you think?

Thank you for your review!

Ciao
Stephan



^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v25 10/12] LRNG - add TRNG support
  2019-11-20 19:51                 ` Stephan Müller
  2019-11-20 19:57                   ` Alexander E. Patrakov
@ 2019-11-20 20:32                   ` Greg Kroah-Hartman
  2019-11-21 13:06                     ` Stephan Müller
  1 sibling, 1 reply; 162+ messages in thread
From: Greg Kroah-Hartman @ 2019-11-20 20:32 UTC (permalink / raw)
  To: Stephan Müller
  Cc: Andy Lutomirski, Arnd Bergmann, Linux Crypto Mailing List, LKML,
	Linux API, Eric W. Biederman, Alexander E. Patrakov,
	Ahmed S. Darwish, Theodore Y. Ts'o, Willy Tarreau,
	Matthew Garrett, Vito Caputo, Andreas Dilger, Jan Kara,
	Ray Strode, William Jon McCann, zhangjs, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

On Wed, Nov 20, 2019 at 08:51:11PM +0100, Stephan Müller wrote:
> Am Mittwoch, 20. November 2019, 14:29:18 CET schrieb Greg Kroah-Hartman:
> 
> Hi Greg,
> 
> > On Wed, Nov 20, 2019 at 09:58:35AM +0100, Stephan Müller wrote:
> > > Am Dienstag, 19. November 2019, 13:41:50 CET schrieb Greg Kroah-Hartman:
> > > 
> > > Hi Greg,
> > > 
> > > > On Tue, Nov 19, 2019 at 02:07:40AM -0800, Andy Lutomirski wrote:
> > > > > > As this would introduce a new device file now, is there a special
> > > > > > process that I need to follow or do I need to copy? Which
> > > > > > major/minor
> > > > > > number should I use?
> > > > > > 
> > > > > > Looking into static const struct memdev devlist[] I see
> > > > > > 
> > > > > >          [8] = { "random", 0666, &random_fops, 0 },
> > > > > >          [9] = { "urandom", 0666, &urandom_fops, 0 },
> > > > > > 
> > > > > > Shall a true_random be added here with [10]?
> > > > > 
> > > > > I am not at all an expert on chardevs, but this sounds generally
> > > > > reasonable.  gregkh is probably the real authority here.
> > > > 
> > > > [10] is the aio char device node, so you better not try to overlap it or
> > > > bad things will happen :(
> > > 
> > > Thanks for your insights.
> > > 
> > > Which device minor number could we use?
> > 
> > Get your own dynamic one by using a misc device if you _REALLY_ want to
> > add yet-another-char-node-for-random-data.
> > 
> > But I would have thought that we all realize that this is not the way to
> > do things.  Let's not have "random", "urandom", and "true_random" be
> > something we want to totally confuse userspace with, that way is insane.
> > 
> > Please just make the existing userspace api "just work", don't add to
> > the mess.
> 
> Thank you, I think we should follow that advise.
> 
> With that and considering Alexander's rightful remark we have a challenge. So, 
> changing the syscall may not be the right way unless we find a way to restrict 
> the permissions somehow (capability? LSM? None of that seems to be a good 
> fit).
> 
> What about providing a /sys file? I.e. adding a file that:
> 
> a) has permissions 440 per default and maybe the ownership of root:root
> 
> b) allow user space to perform a chown/chgrp
> 
> c) only supports reading of data from user space
> 
> But then, how could we provide a common interface for the existing random.c 
> and the LRNG?
> 
> Or should we use a proc file for that? If yes, I guess it should not be a 
> sysctl, but a "regular" proc file that should allow a chown(2) operation. On 
> the other hand, is proc the right place to provide a user space interface for 
> exporting data to user?

No, do not abuse sysfs or procfs for something like this.  Use a real
syscall please if you really need it.

greg k-h

^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v25 12/12] LRNG - add interface for gathering of raw entropy
  2019-11-16  9:38   ` [PATCH v25 12/12] LRNG - add interface for gathering of raw entropy Stephan Müller
  2019-11-16 16:51     ` Andy Lutomirski
  2019-11-19 17:17     ` Randy Dunlap
@ 2019-11-21 12:18     ` Nicolai Stange
  2019-11-21 15:18       ` Stephan Müller
  2 siblings, 1 reply; 162+ messages in thread
From: Nicolai Stange @ 2019-11-21 12:18 UTC (permalink / raw)
  To: Stephan Müller
  Cc: Arnd Bergmann, Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

Hi Stephan,

two general remarks on debugfs usage below

Stephan Müller <smueller@chronox.de> writes:

> diff --git a/drivers/char/lrng/lrng_testing.c b/drivers/char/lrng/lrng_testing.c
> new file mode 100644
> index 000000000000..5c33d3bd2172
> --- /dev/null
> +++ b/drivers/char/lrng/lrng_testing.c

<snip>


> +/*
> + * This data structure holds the dentry's of the debugfs files establishing
> + * the interface to user space.
> + */
> +struct lrng_raw_debugfs {
> +	struct dentry *lrng_raw_debugfs_root; /* root dentry */
> +	struct dentry *lrng_raw_debugfs_lrng_raw; /* .../lrng_raw */
> +};
> +
> +static struct lrng_raw_debugfs lrng_raw_debugfs;
> +
> +/* DebugFS operations and definition of the debugfs files */
> +static ssize_t lrng_raw_read(struct file *file, char __user *to,
> +			     size_t count, loff_t *ppos)
> +{
> +	loff_t pos = *ppos;
> +	int ret;
> +
> +	if (!count)
> +		return 0;
> +	lrng_raw_entropy_init();
> +	ret = lrng_raw_extract_user(to, count);
> +	lrng_raw_entropy_fini();
> +	if (ret < 0)
> +		return ret;
> +	count -= ret;
> +	*ppos = pos + count;
> +	return ret;
> +}
> +
> +/* Module init: allocate memory, register the debugfs files */
> +static int lrng_raw_debugfs_init(void)
> +{
> +	lrng_raw_debugfs.lrng_raw_debugfs_root =
> +		debugfs_create_dir(KBUILD_MODNAME, NULL);
> +	if (IS_ERR(lrng_raw_debugfs.lrng_raw_debugfs_root)) {
> +		lrng_raw_debugfs.lrng_raw_debugfs_root = NULL;
> +		return PTR_ERR(lrng_raw_debugfs.lrng_raw_debugfs_root);
> +	}

I think pointers returned by the debugfs API are not supposed to get
checked for NULL/IS_ERR(), c.f commit ff9fb72bc077 ("debugfs: return
error values, not NULL") or the the output from

  git log --pretty=oneline | grep 'no need to check return value of debugfs_create'

(Also the above code is dubious: you're effectively returning
 PTR_ERR(NULL)).



> +	return 0;
> +}
> +
> +static struct file_operations lrng_raw_name_fops = {
> +	.owner = THIS_MODULE,
> +	.read = lrng_raw_read,
> +};
> +
> +static int lrng_raw_debugfs_init_name(void)
> +{
> +	lrng_raw_debugfs.lrng_raw_debugfs_lrng_raw =
> +		debugfs_create_file("lrng_raw", 0400,
> +				    lrng_raw_debugfs.lrng_raw_debugfs_root,
> +				    NULL, &lrng_raw_name_fops);q

CONFIG_LRNG_TESTING is a bool and thus, this debugfs file can't ever get
removed. Even if it could, this inode hasn't got any data associated
with it and so file removal would not be a problem for lrng_raw_read().

Please consider using debugfs_create_file_unsafe() instead to save
debugfs from kmalloc()ing a proxy file_operations protecting your fops
against concurrent file removal.



> +	if (IS_ERR(lrng_raw_debugfs.lrng_raw_debugfs_lrng_raw)) {
> +		lrng_raw_debugfs.lrng_raw_debugfs_lrng_raw = NULL;
> +		return PTR_ERR(lrng_raw_debugfs.lrng_raw_debugfs_lrng_raw);
> +	}

Same comment regarding return value checking applies here.

Thanks,

Nicolai


> +	return 0;
> +}
> +
> +static int __init lrng_raw_init(void)
> +{
> +	int ret = lrng_raw_debugfs_init();
> +
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = lrng_raw_debugfs_init_name();
> +	if (ret < 0)
> +		debugfs_remove_recursive(
> +					lrng_raw_debugfs.lrng_raw_debugfs_root);
> +
> +	return ret;
> +}
> +
> +static void __exit lrng_raw_exit(void)
> +{
> +	debugfs_remove_recursive(lrng_raw_debugfs.lrng_raw_debugfs_root);
> +}
> +
> +module_init(lrng_raw_init);
> +module_exit(lrng_raw_exit);
> +
> +MODULE_LICENSE("Dual BSD/GPL");
> +MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
> +MODULE_DESCRIPTION("Kernel module for gathering raw entropy");

-- 
SUSE Software Solutions Germany GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg), GF: Felix Imendörffer

^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v25 10/12] LRNG - add TRNG support
  2019-11-20 20:32                   ` Greg Kroah-Hartman
@ 2019-11-21 13:06                     ` Stephan Müller
  0 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-21 13:06 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Andy Lutomirski, Arnd Bergmann, Linux Crypto Mailing List, LKML,
	Linux API, Eric W. Biederman, Alexander E. Patrakov,
	Ahmed S. Darwish, Theodore Y. Ts'o, Willy Tarreau,
	Matthew Garrett, Vito Caputo, Andreas Dilger, Jan Kara,
	Ray Strode, William Jon McCann, zhangjs, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman

Am Mittwoch, 20. November 2019, 21:32:32 CET schrieb Greg Kroah-Hartman:

Hi Greg,

> No, do not abuse sysfs or procfs for something like this.  Use a real
> syscall please if you really need it.

You are right.

Ok, let us get back to the drawing board. What are our requirements? We need 
to have an interface for the TRNG that should ensure other users of entropy 
are not starved by unprivileged users.

What about the following: we use the getrandom(2) system call and add 
GRND_TRUERANDOM as already indicated. However, there is one more caveat we 
would add:

- if the caller of GRND_TRUERANDOM is !CAP_SYS_ADMIN the entropy pool can only 
be depleted to the point where at least one or two full seeding operations 
worth of entropy is left.

- if the caller of GRND_TRUERANDOM is CAP_SYS_ADMIN, the entropy can be 
depleted completely

At runtime, the LRNG would then behave like the following:

- calling getrandom(..., 0), /dev/random or /dev/urandom would deplete the 
entropy pool during reseeding operations but leaving an emergency level of 512 
bits of entropy in the pool. If equal or less are in the pool, reseeding would 
be skipped.

- calling getrandom(..., GRND_TRUERANDOM) with CAP_SYS_ADMIN allows the 
entropy pool to be fully depleted.

- calling getrandom(..., GRND_TRUERANDOM) without CAP_SYS_ADMIN allows the 
entropy pool to be depleted down to 1024 bits of entropy. If the pool has 
equal or less, the caller is blocked. This allows the DRNG feeding /dev/
random, /dev/urandom or getrandom(..., 0) with 512 bits of entropy (i.e. two 
reseed operations are possible). Only if the entropy pool has more than 1024 
bits of entropy, the getrandom call would unblock and provide data.

With that approach, I think we can honor the request from Greg to not add any 
new interface and yet honor the note from Alexander to not allow unprivileged 
user space to deplete the entropy pool to the extent that other users of 
entropy are too much affected.

If GRND_TRUERANDOM is not implemented, EOPNOTSUPP is returned.

Thank you.

Ciao
Stephan



^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v25 09/12] LRNG - add Jitter RNG fast noise source
  2019-11-20 20:07       ` Stephan Müller
@ 2019-11-21 14:19         ` Neil Horman
  2019-11-21 14:33           ` Stephan Mueller
  0 siblings, 1 reply; 162+ messages in thread
From: Neil Horman @ 2019-11-21 14:19 UTC (permalink / raw)
  To: Stephan Müller
  Cc: Arnd Bergmann, Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller

On Wed, Nov 20, 2019 at 09:07:13PM +0100, Stephan Müller wrote:
> Am Mittwoch, 20. November 2019, 14:33:03 CET schrieb Neil Horman:
> 
> Hi Neil,
> 
> > On Sat, Nov 16, 2019 at 10:36:52AM +0100, Stephan Müller wrote:
> > > The Jitter RNG fast noise source implemented as part of the kernel
> > > crypto API is queried for 256 bits of entropy at the time the seed
> > > buffer managed by the LRNG is about to be filled.
> > > 
> > > CC: "Eric W. Biederman" <ebiederm@xmission.com>
> > > CC: "Alexander E. Patrakov" <patrakov@gmail.com>
> > > CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
> > > CC: "Theodore Y. Ts'o" <tytso@mit.edu>
> > > CC: Willy Tarreau <w@1wt.eu>
> > > CC: Matthew Garrett <mjg59@srcf.ucam.org>
> > > CC: Vito Caputo <vcaputo@pengaru.com>
> > > CC: Andreas Dilger <adilger.kernel@dilger.ca>
> > > CC: Jan Kara <jack@suse.cz>
> > > CC: Ray Strode <rstrode@redhat.com>
> > > CC: William Jon McCann <mccann@jhu.edu>
> > > CC: zhangjs <zachary@baishancloud.com>
> > > CC: Andy Lutomirski <luto@kernel.org>
> > > CC: Florian Weimer <fweimer@redhat.com>
> > > CC: Lennart Poettering <mzxreary@0pointer.de>
> > > CC: Nicolai Stange <nstange@suse.de>
> > > Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
> > > Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
> > > Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
> > > Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
> > > Tested-by: Neil Horman <nhorman@redhat.com>
> > > Signed-off-by: Stephan Mueller <smueller@chronox.de>
> > > ---
> > > 
> > >  drivers/char/lrng/Kconfig     | 11 +++++
> > >  drivers/char/lrng/Makefile    |  1 +
> > >  drivers/char/lrng/lrng_jent.c | 88 +++++++++++++++++++++++++++++++++++
> > >  3 files changed, 100 insertions(+)
> > >  create mode 100644 drivers/char/lrng/lrng_jent.c
> > > 
> > > diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
> > > index 03e6e2ec356b..80fc723c67d2 100644
> > > --- a/drivers/char/lrng/Kconfig
> > > +++ b/drivers/char/lrng/Kconfig
> > > @@ -80,4 +80,15 @@ config LRNG_KCAPI
> > > 
> > >  	  provided by the selected kernel crypto API RNG.
> > >  
> > >  endif # LRNG_DRNG_SWITCH
> > > 
> > > +config LRNG_JENT
> > > +	bool "Enable Jitter RNG as LRNG Seed Source"
> > > +	select CRYPTO_JITTERENTROPY
> > > +	help
> > > +	  The Linux RNG may use the Jitter RNG as noise source. Enabling
> > > +	  this option enables the use of the Jitter RNG. Its default
> > > +	  entropy level is 16 bits of entropy per 256 data bits delivered
> > > +	  by the Jitter RNG. This entropy level can be changed at boot
> > > +	  time or at runtime with the lrng_base.jitterrng configuration
> > > +	  variable.
> > > +
> > > 
> > >  endif # LRNG
> > > 
> > > diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
> > > index 027b6ea51c20..a87d800c9aae 100644
> > > --- a/drivers/char/lrng/Makefile
> > > +++ b/drivers/char/lrng/Makefile
> > > @@ -13,3 +13,4 @@ obj-$(CONFIG_SYSCTL)		+= lrng_proc.o
> > > 
> > >  obj-$(CONFIG_LRNG_DRNG_SWITCH)	+= lrng_switch.o
> > >  obj-$(CONFIG_LRNG_DRBG)		+= lrng_drbg.o
> > >  obj-$(CONFIG_LRNG_KCAPI)	+= lrng_kcapi.o
> > > 
> > > +obj-$(CONFIG_LRNG_JENT)		+= lrng_jent.o
> > > diff --git a/drivers/char/lrng/lrng_jent.c b/drivers/char/lrng/lrng_jent.c
> > > new file mode 100644
> > > index 000000000000..43114a44b8f5
> > > --- /dev/null
> > > +++ b/drivers/char/lrng/lrng_jent.c
> > > @@ -0,0 +1,88 @@
> > > +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
> > > +/*
> > > + * LRNG Fast Noise Source: Jitter RNG
> > > + *
> > > + * Copyright (C) 2016 - 2019, Stephan Mueller <smueller@chronox.de>
> > > + */
> > > +
> > > +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> > > +
> > > +#include "lrng_internal.h"
> > > +
> > > +/*
> > > + * Estimated entropy of data is a 16th of
> > > LRNG_DRNG_SECURITY_STRENGTH_BITS. + * Albeit a full entropy assessment is
> > > provided for the noise source indicating + * that it provides high
> > > entropy rates and considering that it deactivates + * when it detects
> > > insufficient hardware, the chosen under estimation of + * entropy is
> > > considered to be acceptable to all reviewers.
> > > + */
> > > +static u32 jitterrng = LRNG_DRNG_SECURITY_STRENGTH_BITS>>4;
> > > +module_param(jitterrng, uint, 0644);
> > > +MODULE_PARM_DESC(jitterrng, "Entropy in bits of 256 data bits from Jitter
> > > " +			    "RNG noise source");
> > > +
> > > +/**
> > > + * Get Jitter RNG entropy
> > > + *
> > > + * @outbuf buffer to store entropy
> > > + * @outbuflen length of buffer
> > > + * @return > 0 on success where value provides the added entropy in bits
> > > + *	   0 if no fast source was available
> > > + */
> > > +struct rand_data;
> > > +struct rand_data *jent_lrng_entropy_collector(void);
> > > +int jent_read_entropy(struct rand_data *ec, unsigned char *data,
> > > +		      unsigned int len);
> > > +static struct rand_data *lrng_jent_state;
> > > +
> > > +u32 lrng_get_jent(u8 *outbuf, unsigned int outbuflen)
> > > +{
> > > +	int ret;
> > > +	u32 ent_bits = jitterrng;
> > > +	unsigned long flags;
> > > +	static DEFINE_SPINLOCK(lrng_jent_lock);
> > > +	static int lrng_jent_initialized = 0;
> > > +
> > > +	spin_lock_irqsave(&lrng_jent_lock, flags);
> > > +
> > > +	if (!ent_bits || (lrng_jent_initialized == -1)) {
> > > +		spin_unlock_irqrestore(&lrng_jent_lock, flags);
> > > +		return 0;
> > > +	}
> > > +
> > 
> > this works, but I think you can avoid the use of the spin lock on the read
> > calls here.  If you assign a global pointer to the value of
> > &lrng_jent_state on init, you can just take the spinlock on assignment, and
> > assume its stable after that (which it should be given that its only ever
> > going to point to a static data structure).
> 
> It is correct that the lock protects the assignment of the data structure.
> 
> But the Jitter RNG itself is not multi-threaded. So, a form of serialization 
> is needed to also "read" data from the Jitter RNG using one and the same 
> state.
> 
> Granted, there is a serialization in the current code as the 
> lrng_pool_trylock() is taken before the Jitter RNG is called by 
> lrng_fill_seed_buffer which effectively serializes all requests to also the 
> Jitter RNG. But this is coincidence in this case. I would think, however, that 
> this coincidence could easily lead to programming errors further down the road 
> when the spinlock is not present and that trylock() is moved to some place 
> else considering that this trylock() is meant to protect reading the entropy 
> pool and not the Jitter RNG.
> 
> As the reading of the Jitter RNG is always performed in process context, I 
> think having this additional spin lock against possible programming errors 
> should not lead to performance regressions.
> 
> What do you think?
> 
I take your meaning that each random device needs protection, and yes, each of
the random devices (trng and sdrng) have their own locking.  But it also appears
to me that each of those random devices contains its own private copy of the
entropy_buf (they're statically declared on the stack in lrng_trng_seed and
_lrng_sdrng_seed), so while the additional locking doesn't necessecarily hurt,
I'm struggling to see why the additional work is needed.  If ever you have a
situation in which multiple rngs want want to share an entropy buffer, yes, you
would need that lock, or some other protection, but I don't see the need
immediately.

Neil

> Thank you for your review!
> 
> Ciao
> Stephan
> 
> 


^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v25 09/12] LRNG - add Jitter RNG fast noise source
  2019-11-21 14:19         ` Neil Horman
@ 2019-11-21 14:33           ` Stephan Mueller
  0 siblings, 0 replies; 162+ messages in thread
From: Stephan Mueller @ 2019-11-21 14:33 UTC (permalink / raw)
  To: Neil Horman
  Cc: Arnd Bergmann, Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller

Am Donnerstag, 21. November 2019, 15:19:30 CET schrieb Neil Horman:

Hi Neil,

> On Wed, Nov 20, 2019 at 09:07:13PM +0100, Stephan Müller wrote:
> > Am Mittwoch, 20. November 2019, 14:33:03 CET schrieb Neil Horman:
> > 
> > Hi Neil,
> > 
> > > On Sat, Nov 16, 2019 at 10:36:52AM +0100, Stephan Müller wrote:
> > > > The Jitter RNG fast noise source implemented as part of the kernel
> > > > crypto API is queried for 256 bits of entropy at the time the seed
> > > > buffer managed by the LRNG is about to be filled.
> > > > 
> > > > CC: "Eric W. Biederman" <ebiederm@xmission.com>
> > > > CC: "Alexander E. Patrakov" <patrakov@gmail.com>
> > > > CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
> > > > CC: "Theodore Y. Ts'o" <tytso@mit.edu>
> > > > CC: Willy Tarreau <w@1wt.eu>
> > > > CC: Matthew Garrett <mjg59@srcf.ucam.org>
> > > > CC: Vito Caputo <vcaputo@pengaru.com>
> > > > CC: Andreas Dilger <adilger.kernel@dilger.ca>
> > > > CC: Jan Kara <jack@suse.cz>
> > > > CC: Ray Strode <rstrode@redhat.com>
> > > > CC: William Jon McCann <mccann@jhu.edu>
> > > > CC: zhangjs <zachary@baishancloud.com>
> > > > CC: Andy Lutomirski <luto@kernel.org>
> > > > CC: Florian Weimer <fweimer@redhat.com>
> > > > CC: Lennart Poettering <mzxreary@0pointer.de>
> > > > CC: Nicolai Stange <nstange@suse.de>
> > > > Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
> > > > Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
> > > > Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
> > > > Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
> > > > Tested-by: Neil Horman <nhorman@redhat.com>
> > > > Signed-off-by: Stephan Mueller <smueller@chronox.de>
> > > > ---
> > > > 
> > > >  drivers/char/lrng/Kconfig     | 11 +++++
> > > >  drivers/char/lrng/Makefile    |  1 +
> > > >  drivers/char/lrng/lrng_jent.c | 88
> > > >  +++++++++++++++++++++++++++++++++++
> > > >  3 files changed, 100 insertions(+)
> > > >  create mode 100644 drivers/char/lrng/lrng_jent.c
> > > > 
> > > > diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
> > > > index 03e6e2ec356b..80fc723c67d2 100644
> > > > --- a/drivers/char/lrng/Kconfig
> > > > +++ b/drivers/char/lrng/Kconfig
> > > > @@ -80,4 +80,15 @@ config LRNG_KCAPI
> > > > 
> > > >  	  provided by the selected kernel crypto API RNG.
> > > >  
> > > >  endif # LRNG_DRNG_SWITCH
> > > > 
> > > > +config LRNG_JENT
> > > > +	bool "Enable Jitter RNG as LRNG Seed Source"
> > > > +	select CRYPTO_JITTERENTROPY
> > > > +	help
> > > > +	  The Linux RNG may use the Jitter RNG as noise source. 
Enabling
> > > > +	  this option enables the use of the Jitter RNG. Its default
> > > > +	  entropy level is 16 bits of entropy per 256 data bits 
delivered
> > > > +	  by the Jitter RNG. This entropy level can be changed at 
boot
> > > > +	  time or at runtime with the lrng_base.jitterrng 
configuration
> > > > +	  variable.
> > > > +
> > > > 
> > > >  endif # LRNG
> > > > 
> > > > diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
> > > > index 027b6ea51c20..a87d800c9aae 100644
> > > > --- a/drivers/char/lrng/Makefile
> > > > +++ b/drivers/char/lrng/Makefile
> > > > @@ -13,3 +13,4 @@ obj-$(CONFIG_SYSCTL)		+= lrng_proc.o
> > > > 
> > > >  obj-$(CONFIG_LRNG_DRNG_SWITCH)	+= lrng_switch.o
> > > >  obj-$(CONFIG_LRNG_DRBG)		+= lrng_drbg.o
> > > >  obj-$(CONFIG_LRNG_KCAPI)	+= lrng_kcapi.o
> > > > 
> > > > +obj-$(CONFIG_LRNG_JENT)		+= lrng_jent.o
> > > > diff --git a/drivers/char/lrng/lrng_jent.c
> > > > b/drivers/char/lrng/lrng_jent.c
> > > > new file mode 100644
> > > > index 000000000000..43114a44b8f5
> > > > --- /dev/null
> > > > +++ b/drivers/char/lrng/lrng_jent.c
> > > > @@ -0,0 +1,88 @@
> > > > +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
> > > > +/*
> > > > + * LRNG Fast Noise Source: Jitter RNG
> > > > + *
> > > > + * Copyright (C) 2016 - 2019, Stephan Mueller <smueller@chronox.de>
> > > > + */
> > > > +
> > > > +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> > > > +
> > > > +#include "lrng_internal.h"
> > > > +
> > > > +/*
> > > > + * Estimated entropy of data is a 16th of
> > > > LRNG_DRNG_SECURITY_STRENGTH_BITS. + * Albeit a full entropy assessment
> > > > is
> > > > provided for the noise source indicating + * that it provides high
> > > > entropy rates and considering that it deactivates + * when it detects
> > > > insufficient hardware, the chosen under estimation of + * entropy is
> > > > considered to be acceptable to all reviewers.
> > > > + */
> > > > +static u32 jitterrng = LRNG_DRNG_SECURITY_STRENGTH_BITS>>4;
> > > > +module_param(jitterrng, uint, 0644);
> > > > +MODULE_PARM_DESC(jitterrng, "Entropy in bits of 256 data bits from
> > > > Jitter
> > > > " +			    "RNG noise source");
> > > > +
> > > > +/**
> > > > + * Get Jitter RNG entropy
> > > > + *
> > > > + * @outbuf buffer to store entropy
> > > > + * @outbuflen length of buffer
> > > > + * @return > 0 on success where value provides the added entropy in
> > > > bits
> > > > + *	   0 if no fast source was available
> > > > + */
> > > > +struct rand_data;
> > > > +struct rand_data *jent_lrng_entropy_collector(void);
> > > > +int jent_read_entropy(struct rand_data *ec, unsigned char *data,
> > > > +		      unsigned int len);
> > > > +static struct rand_data *lrng_jent_state;
> > > > +
> > > > +u32 lrng_get_jent(u8 *outbuf, unsigned int outbuflen)
> > > > +{
> > > > +	int ret;
> > > > +	u32 ent_bits = jitterrng;
> > > > +	unsigned long flags;
> > > > +	static DEFINE_SPINLOCK(lrng_jent_lock);
> > > > +	static int lrng_jent_initialized = 0;
> > > > +
> > > > +	spin_lock_irqsave(&lrng_jent_lock, flags);
> > > > +
> > > > +	if (!ent_bits || (lrng_jent_initialized == -1)) {
> > > > +		spin_unlock_irqrestore(&lrng_jent_lock, flags);
> > > > +		return 0;
> > > > +	}
> > > > +
> > > 
> > > this works, but I think you can avoid the use of the spin lock on the
> > > read
> > > calls here.  If you assign a global pointer to the value of
> > > &lrng_jent_state on init, you can just take the spinlock on assignment,
> > > and
> > > assume its stable after that (which it should be given that its only
> > > ever
> > > going to point to a static data structure).
> > 
> > It is correct that the lock protects the assignment of the data structure.
> > 
> > But the Jitter RNG itself is not multi-threaded. So, a form of
> > serialization is needed to also "read" data from the Jitter RNG using one
> > and the same state.
> > 
> > Granted, there is a serialization in the current code as the
> > lrng_pool_trylock() is taken before the Jitter RNG is called by
> > lrng_fill_seed_buffer which effectively serializes all requests to also
> > the
> > Jitter RNG. But this is coincidence in this case. I would think, however,
> > that this coincidence could easily lead to programming errors further
> > down the road when the spinlock is not present and that trylock() is
> > moved to some place else considering that this trylock() is meant to
> > protect reading the entropy pool and not the Jitter RNG.
> > 
> > As the reading of the Jitter RNG is always performed in process context, I
> > think having this additional spin lock against possible programming errors
> > should not lead to performance regressions.
> > 
> > What do you think?
> 
> I take your meaning that each random device needs protection, and yes, each
> of the random devices (trng and sdrng) have their own locking.  But it also
> appears to me that each of those random devices contains its own private
> copy of the entropy_buf (they're statically declared on the stack in
> lrng_trng_seed and _lrng_sdrng_seed), so while the additional locking
> doesn't necessecarily hurt, I'm struggling to see why the additional work
> is needed.

This lock around the Jitter RNG is needed if:

1) TRNG is not configured

2) NUMA is configured, and

3) we have more than one NUMA node.

In this case it is possible that the lrng_fill_seed_buf is called in parallel 
by parallel executions of the secondary DRNG seeding operation on the 
different NUMA nodes.

In this case it is possible that the one global Jitter RNG state is used to 
request random numbers in parallel. This scenario requires the lock.

Thank you.

> If ever you have a situation in which multiple rngs want want
> to share an entropy buffer, yes, you would need that lock, or some other
> protection, but I don't see the need immediately.
> 
> Neil
> 
> > Thank you for your review!
> > 
> > Ciao
> > Stephan



Ciao
Stephan



^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v25 12/12] LRNG - add interface for gathering of raw entropy
  2019-11-21 12:18     ` Nicolai Stange
@ 2019-11-21 15:18       ` Stephan Müller
  0 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-21 15:18 UTC (permalink / raw)
  To: Nicolai Stange
  Cc: Arnd Bergmann, Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Peter, Matthias, Marcelo Henrique Cerri,
	Roman Drahtmueller, Neil Horman

Am Donnerstag, 21. November 2019, 13:18:10 CET schrieb Nicolai Stange:

Hi Nicolai,

> Hi Stephan,
> 
> two general remarks on debugfs usage below
> 
> Stephan Müller <smueller@chronox.de> writes:
> > diff --git a/drivers/char/lrng/lrng_testing.c
> > b/drivers/char/lrng/lrng_testing.c new file mode 100644
> > index 000000000000..5c33d3bd2172
> > --- /dev/null
> > +++ b/drivers/char/lrng/lrng_testing.c
> 
> <snip>
> 
> > +/*
> > + * This data structure holds the dentry's of the debugfs files
> > establishing + * the interface to user space.
> > + */
> > +struct lrng_raw_debugfs {
> > +	struct dentry *lrng_raw_debugfs_root; /* root dentry */
> > +	struct dentry *lrng_raw_debugfs_lrng_raw; /* .../lrng_raw */
> > +};
> > +
> > +static struct lrng_raw_debugfs lrng_raw_debugfs;
> > +
> > +/* DebugFS operations and definition of the debugfs files */
> > +static ssize_t lrng_raw_read(struct file *file, char __user *to,
> > +			     size_t count, loff_t *ppos)
> > +{
> > +	loff_t pos = *ppos;
> > +	int ret;
> > +
> > +	if (!count)
> > +		return 0;
> > +	lrng_raw_entropy_init();
> > +	ret = lrng_raw_extract_user(to, count);
> > +	lrng_raw_entropy_fini();
> > +	if (ret < 0)
> > +		return ret;
> > +	count -= ret;
> > +	*ppos = pos + count;
> > +	return ret;
> > +}
> > +
> > +/* Module init: allocate memory, register the debugfs files */
> > +static int lrng_raw_debugfs_init(void)
> > +{
> > +	lrng_raw_debugfs.lrng_raw_debugfs_root =
> > +		debugfs_create_dir(KBUILD_MODNAME, NULL);
> > +	if (IS_ERR(lrng_raw_debugfs.lrng_raw_debugfs_root)) {
> > +		lrng_raw_debugfs.lrng_raw_debugfs_root = NULL;
> > +		return PTR_ERR(lrng_raw_debugfs.lrng_raw_debugfs_root);
> > +	}
> 
> I think pointers returned by the debugfs API are not supposed to get
> checked for NULL/IS_ERR(), c.f commit ff9fb72bc077 ("debugfs: return
> error values, not NULL") or the the output from
> 
>   git log --pretty=oneline | grep 'no need to check return value of
> debugfs_create'
> 
> (Also the above code is dubious: you're effectively returning
>  PTR_ERR(NULL)).

Removed the check compliant to the mentioned patches.
> 
> > +	return 0;
> > +}
> > +
> > +static struct file_operations lrng_raw_name_fops = {
> > +	.owner = THIS_MODULE,
> > +	.read = lrng_raw_read,
> > +};
> > +
> > +static int lrng_raw_debugfs_init_name(void)
> > +{
> > +	lrng_raw_debugfs.lrng_raw_debugfs_lrng_raw =
> > +		debugfs_create_file("lrng_raw", 0400,
> > +				    lrng_raw_debugfs.lrng_raw_debugfs_root,
> > +				    NULL, &lrng_raw_name_fops);q
> 
> CONFIG_LRNG_TESTING is a bool and thus, this debugfs file can't ever get
> removed. Even if it could, this inode hasn't got any data associated
> with it and so file removal would not be a problem for lrng_raw_read().

Correct.
> 
> Please consider using debugfs_create_file_unsafe() instead to save
> debugfs from kmalloc()ing a proxy file_operations protecting your fops
> against concurrent file removal.

Yes, you are correct. Changed.
> 
> > +	if (IS_ERR(lrng_raw_debugfs.lrng_raw_debugfs_lrng_raw)) {
> > +		lrng_raw_debugfs.lrng_raw_debugfs_lrng_raw = NULL;
> > +		return PTR_ERR(lrng_raw_debugfs.lrng_raw_debugfs_lrng_raw);
> > +	}
> 
> Same comment regarding return value checking applies here.

Same here: I removed the check.

With that, I also removed the static variable to maintain the two dentries 
following the examples seen in other kernel code. Also, the __exit function is 
removed as we do not need it as you pointed out.

Thanks a lot.
> 
> Thanks,
> 
> Nicolai
> 
> > +	return 0;
> > +}
> > +
> > +static int __init lrng_raw_init(void)
> > +{
> > +	int ret = lrng_raw_debugfs_init();
> > +
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	ret = lrng_raw_debugfs_init_name();
> > +	if (ret < 0)
> > +		debugfs_remove_recursive(
> > +					lrng_raw_debugfs.lrng_raw_debugfs_root);
> > +
> > +	return ret;
> > +}
> > +
> > +static void __exit lrng_raw_exit(void)
> > +{
> > +	debugfs_remove_recursive(lrng_raw_debugfs.lrng_raw_debugfs_root);
> > +}
> > +
> > +module_init(lrng_raw_init);
> > +module_exit(lrng_raw_exit);
> > +
> > +MODULE_LICENSE("Dual BSD/GPL");
> > +MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
> > +MODULE_DESCRIPTION("Kernel module for gathering raw entropy");


Ciao
Stephan



^ permalink raw reply	[flat|nested] 162+ messages in thread

* [PATCH v26 00/12] /dev/random - a new approach with full SP800-90B
  2019-11-16  9:32 ` [PATCH v25 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                     ` (11 preceding siblings ...)
  2019-11-16  9:38   ` [PATCH v25 12/12] LRNG - add interface for gathering of raw entropy Stephan Müller
@ 2019-11-23 20:08   ` Stephan Müller
  2019-11-23 20:10     ` [PATCH v26 01/12] Linux Random Number Generator Stephan Müller
                       ` (12 more replies)
  12 siblings, 13 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-23 20:08 UTC (permalink / raw)
  To: Stephan Müller
  Cc: Arnd Bergmann, Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap

Hi,

The following patch set provides a different approach to /dev/random which is
called Linux Random Number Generator (LRNG) to collect entropy within the Linux
kernel. The main improvements compared to the existing /dev/random is to provide
sufficient entropy during boot time as well as in virtual environments and when
using SSDs. A secondary design goal is to limit the impact of the entropy
collection on massive parallel systems and also allow the use accelerated
cryptographic primitives. Also, all steps of the entropic data processing are
testable.

The LRNG patch set allows a user to select use of the existing /dev/random or
the LRNG during compile time. As the LRNG provides API and ABI compatible
interfaces to the existing /dev/random implementation, the user can freely chose
the RNG implementation without affecting kernel or user space operations.

This patch set provides early boot-time entropy which implies that no
additional flags to the getrandom(2) system call discussed recently on
the LKML is considered to be necessary. Yet, if additional flags are
introduced to cover special hardware, the LRNG implementation will also
provide them to be fully ABI and API compliant as already discussed on
LKML.

The LRNG is fully compliant to SP800-90B requirements and is shipped with a
full SP800-90B assessment and all required test tools. The existing /dev/random
implementation on the other hand has architectural limitations which
does not easily allow to bring the implementation in compliance with
SP800-90B. The key statement that causes concern is SP800-90B section
3.1.6. This section denies crediting entropy to multiple similar noise
sources. This section explicitly references different noise sources resting
on the timing of events and their derivatives (i.e. it is a direct complaint
to the existing existing /dev/random implementation). Therefore, SP800-90B
now denies the very issue mentioned in [1] with the existing /dev/random
implementation for a long time: crediting entropy to interrupts as well as
crediting entropy to derivatives of interrupts (HID and disk events). This is
not permissible with SP800-90B.

SP800-90B specifies various requirements for the noise source(s) that seed any
DRNG including SP800-90A DRBGs. In about a year from now, SP800-90B will be
mandated for all noise sources that provide entropy to DRBGs as part of a FIPS
140-[2|3] validation or other evaluation types. That means, if we there are no
solutions to comply with the requirements of SP800-90B found till one year
from now, any random number generation and ciphers based on random numbers
on Linux will be considered and treated as not applicable and delivering
no entropy! As /dev/urandom, getrandom(2) and /dev/random are the most
common and prevalent noise sources for DRNGs, all these DRNGs are affected.
This applies across the board for all validations of cryptography executing on
Linux (kernel and user space modules).

For users that are not interested in SP800-90B, the entire code for the
compliance as well as test interfaces can be deselected at compile time.

The design and implementation is driven by a set of goals described in [1]
that the LRNG completely implements. Furthermore, [1] includes the full
assessment of the SP800-90B compliance as well as a comparison with RNG
design suggestions of SP800-90C, and AIS20/31.

The LRNG provides a complete separation of the noise source maintenance
and the collection of entropy into an entropy pool from the post-processing
using a pseudo-random number generator. Different DRNGs are supported,
including:

* The LRNG can be compile-time enabled to replace the existing /dev/random
  implementation. When not selecting the LRNG at compile time (default), the
  existing /dev/random implementation is built.

* Built-in ChaCha20 DRNG which has no dependency to other kernel
  frameworks.

* SP800-90A DRBG using the kernel crypto API including its accelerated
  raw cipher implementations. This implies that the output of /dev/random,
  getrandom(2), /dev/urandom or get_random_bytes is fully compliant to
  SP800-90A.

* Arbitrary DRNGs registered with the kernel crypto API

* Full compliance with SP800-90B which covers the startup and runtime health
  tests mandated by SP800-90B as well as providing the test tools and test
  interfaces to obtain raw noise data securely. The test tools are provided at
  [1].

Booting the patch with the kernel command line option
"dyndbg=file drivers/char/lrng/* +p" generates logs indicating the operation
of the LRNG. Each log is pre-pended with "lrng".

The LRNG has a flexible design by allowing an easy replacement of the
deterministic random number generator component.

Compared to the existing /dev/random implementation, the compiled binary
is smaller when the LRNG is compiled with all options equal to the
existing /dev/random (i.e. only CONFIG_LRNG and
CONFIG_LRNG_TRNG_SUPPORT are set): random.o is 52.5 kBytes whereas
all LRNG object files are in 49 kBytes in size. The fully
SP800-90A/SP800-90B compliant binary code (CONFIG_LRNG,
CONFIG_LRNG_DRNG_SWITCH, CONFIG_LRNG_DRBG, CONFIG_LRNG_HEALTH_TESTS)
uses some 61 kBytes.

[1] http://www.chronox.de/lrng.html - If the patch is accepted, I would
be volunteering to convert the documentation into RST format and
contribute it to the Linux kernel documentation directory.

Changes (compared to the previous patch set):

* Extract the time initalization code into its own function
  lrng_init_time_source and invoke it with core_initcall as reported
  by Nicolai Stange

* Add linux/errno.h include to lrng.h as suggested by Nicolai Stange

* Add linux/slab.h to lrng_chacha20.h

* Changed lrng_testing.c reading/writing of ring buffer to use a lock
  as suggested by Andy Lutomirski

* Use "depends on DEBUG_FS" for lrng_testing.c Kconfig entry as
  suggested by Randy Dunlap

* Remove declaration of random_table from lrng_proc.c as suggested by
  Eric W. Biederman

* Move the lrng_type file out of the sysctl table into its own file
  /proc/lrng_type since its purpose is not to serve as a sysctl
  as suggested by Eric W. Biederman

* Update patch description for /proc patch to refer to sysctls as suggested
  by Eric W. Biederman

* /dev/random and getrandom(GRND_RANDOM) now invokes the secondary DRNG
  ensuring that the DRNG is fully seeded before requests are served. With
  this change, /dev/random is no TRNG any more. This change implements
  the suggestion from Andy Lutomirski and is based on the discussions
  previously on the LKML and the changes developed by Andy for the existing
  random.c implementation.

* Simplification of the debugfs code in lrng_testing.c as return code
  checks are not further needed any more as suggested by Nicolai Stange.

* Addition of GRND_TRUERANDOM to the getrandom(2) syscall to make the TRNG
  externally accessible as a TRNG. The change also includes the GRND_INSECURE
  flag as proposed by Andy Lutomirski. To avoid touching the random.h and
  potentially clashing with Andy's patch set, I kept the symbol definitions
  in lrng_interfaces.c noting that they should be moved to random.h. The
  GRND_TRUERANDOM allows unprivileged user space to access the TRNG as follows:
  if CAP_SYS_ADMIN calls, the whole entropy available to the LRNG is used. If
  an unprivileged process invokes GRND_TRUERANDOM, at least 1024 bits of entropy
  will remain in the pool to serve CAP_SYS_ADMIN and all secondary DRNGs
  serving /dev/urandom, /dev/random and getrandom(.., 0) with entropy. With
  that unprivileged processes calling GRND_TRUERANDOM have the lowest priority
  in getting entropy and must wait accordingly. If the TRNG is not present,
  GRND_TRUERANDOM returns -EOPNOTSUPP. A new test tool is provided as part
  of the LRNG test archive found at [1] allowing to analyze all four types
  of RNGs accessible via getrandom(2).

* Remove duplication of MODULE_LICENSE/AUTHOR/DESCRIPTION from lrng_testing.c

A patch for adding power-up self tests is prepared but I did not want to add it
now to support code review of a code base with minimal changes. It will be
provided once the code review is completed. With this pending code, the
following tests are available:

* power-on self test: LFSR self test

* power-on self test: ChaCha20 DRNG self test

* power-on self test: time stamp array handling in lrng_sw_noise.c

* power-on self test: SP800-90A DRBG self test

* runtime test: raw noise source data collection, if enabled

* separate test: SP800-90B APT and RCT test enforcement validation if enabled

As a side node: With the switchable DRNG support offered in this patch set,
the following areas could be removed. As the existing /dev/random has no support
for switchable DRNGs, however, this is not yet feasible though.

* remove lrng_ready_list and all code around it in lrng_interfaces.c

* remove the kernel crypto API RNG API to avoid having two random number
  providing APIs - this would imply that all RNGs developed for this API would
  be converted to the LRNG interface

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>

Stephan Mueller (12):
  Linux Random Number Generator
  LRNG - allocate one SDRNG instance per NUMA node
  LRNG - sysctls and /proc interface
  LRNG - add switchable DRNG support
  crypto: DRBG - externalize DRBG functions for LRNG
  LRNG - add SP800-90A DRBG extension
  LRNG - add kernel crypto API PRNG extension
  crypto: provide access to a static Jitter RNG state
  LRNG - add Jitter RNG fast noise source
  LRNG - add TRNG support
  LRNG - add SP800-90B compliant health tests
  LRNG - add interface for gathering of raw entropy

 MAINTAINERS                         |   7 +
 crypto/drbg.c                       |  16 +-
 crypto/jitterentropy.c              |  23 +
 drivers/char/Kconfig                |   2 +
 drivers/char/Makefile               |   9 +-
 drivers/char/lrng/Kconfig           | 188 ++++++++
 drivers/char/lrng/Makefile          |  19 +
 drivers/char/lrng/lrng_archrandom.c |  92 ++++
 drivers/char/lrng/lrng_aux.c        | 148 ++++++
 drivers/char/lrng/lrng_chacha20.c   | 329 ++++++++++++++
 drivers/char/lrng/lrng_drbg.c       | 261 +++++++++++
 drivers/char/lrng/lrng_health.c     | 409 +++++++++++++++++
 drivers/char/lrng/lrng_interfaces.c | 665 +++++++++++++++++++++++++++
 drivers/char/lrng/lrng_internal.h   | 320 +++++++++++++
 drivers/char/lrng/lrng_jent.c       |  88 ++++
 drivers/char/lrng/lrng_kcapi.c      | 328 ++++++++++++++
 drivers/char/lrng/lrng_numa.c       | 101 +++++
 drivers/char/lrng/lrng_pool.c       | 671 ++++++++++++++++++++++++++++
 drivers/char/lrng/lrng_proc.c       | 179 ++++++++
 drivers/char/lrng/lrng_sdrng.c      | 420 +++++++++++++++++
 drivers/char/lrng/lrng_sw_noise.c   | 144 ++++++
 drivers/char/lrng/lrng_switch.c     | 185 ++++++++
 drivers/char/lrng/lrng_testing.c    | 269 +++++++++++
 drivers/char/lrng/lrng_trng.c       | 297 ++++++++++++
 include/crypto/drbg.h               |   7 +
 include/linux/lrng.h                |  71 +++
 26 files changed, 5241 insertions(+), 7 deletions(-)
 create mode 100644 drivers/char/lrng/Kconfig
 create mode 100644 drivers/char/lrng/Makefile
 create mode 100644 drivers/char/lrng/lrng_archrandom.c
 create mode 100644 drivers/char/lrng/lrng_aux.c
 create mode 100644 drivers/char/lrng/lrng_chacha20.c
 create mode 100644 drivers/char/lrng/lrng_drbg.c
 create mode 100644 drivers/char/lrng/lrng_health.c
 create mode 100644 drivers/char/lrng/lrng_interfaces.c
 create mode 100644 drivers/char/lrng/lrng_internal.h
 create mode 100644 drivers/char/lrng/lrng_jent.c
 create mode 100644 drivers/char/lrng/lrng_kcapi.c
 create mode 100644 drivers/char/lrng/lrng_numa.c
 create mode 100644 drivers/char/lrng/lrng_pool.c
 create mode 100644 drivers/char/lrng/lrng_proc.c
 create mode 100644 drivers/char/lrng/lrng_sdrng.c
 create mode 100644 drivers/char/lrng/lrng_sw_noise.c
 create mode 100644 drivers/char/lrng/lrng_switch.c
 create mode 100644 drivers/char/lrng/lrng_testing.c
 create mode 100644 drivers/char/lrng/lrng_trng.c
 create mode 100644 include/linux/lrng.h

-- 
2.23.0





^ permalink raw reply	[flat|nested] 162+ messages in thread

* [PATCH v26 01/12] Linux Random Number Generator
  2019-11-23 20:08   ` [PATCH v26 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
@ 2019-11-23 20:10     ` Stephan Müller
  2019-11-24 22:44       ` kbuild test robot
  2019-11-23 20:10     ` [PATCH v26 02/12] LRNG - allocate one SDRNG instance per NUMA node Stephan Müller
                       ` (11 subsequent siblings)
  12 siblings, 1 reply; 162+ messages in thread
From: Stephan Müller @ 2019-11-23 20:10 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap

In an effort to provide a flexible implementation for a random number
generator that also delivers entropy during early boot time, allows
replacement of the deterministic random number generation mechanism,
implement the various components in separate code for easier
maintenance, and provide compliance to SP800-90[A|B|C], introduce
the Linux Random Number Generator (LRNG) framework.

The general design is as follows. Additional implementation details
are given in [1]. The LRNG consists of the following components:

1. The LRNG may contain a True Random Number Generator (TRNG). The
TRNG is a deterministic random number generator that is operated as
a true random number generator. Using SP800-90A terminology, the
TRNG is a DRBG with prediction resistance. The TRNG has a behavior
similar to SP800-90A's concept of prediction resistance by only
generating output when it is re-seeded with an equal amount of
entropy. Every time a caller requests random numbers, the TRNG
must be re-seeded with at least that amount of entropy from its noise
sources. During boot time, the TRNG is not yet operated with
prediction resistance. As the external interfaces to the TRNG to
obtain random numbers start to be accessible after boot time
completes, random numbers generated via these interfaces always
access the TRNG that is operated with prediction resistance.

2. The LRNG implements a secondary DRNG. The secondary DRNG always
generates the requested amount of output. When using the SP800-90A
terminology it operates without prediction resistance. The secondary
DRNG maintains a counter of how many bytes were generated since last
re-seed and a timer of the elapsed time since last re-seed. If either
the counter or the timer reaches a threshold, the secondary DRNG is
seeded from the TRNG.

In case the Linux kernel detects a NUMA system, one secondary DRNG
instance per NUMA node is maintained.

3. The TRNG is seeded by concatenating the data from the
following sources:

(a) the output of the entropy pool,

(b) the Jitter RNG if available and enabled, and

(c) the CPU-based noise source such as Intel RDRAND if available and
enabled.

The entropy estimate of the data of all noise sources are added to
form the entropy estimate of the data used to seed the TRNG with.
The LRNG ensures, however, that the TRNG after seeding is at
maximum the security strength of the TRNG.

The LRNG is designed such that none of these noise sources can dominate
the other noise sources to provide seed data to the TRNG during
boot time due to the following:

(a) During boot time, the amount of received interrupts are the trigger
points to (re)seed the TRNG.

(b) At runtime, the caller requesting random numbers from the primary
TRNG drives the reseeding where always as much entropy as available is
used to reseed the TRNG.

4. The entropy pool accumulates entropy obtained from certain events,
which will henceforth be collectively called "slow noise sources".
The entropy pool collects noise data from slow noise sources. Any data
received by the LRNG from the slow noise sources is inserted into the
entropy pool using an LFSR with a primitive and irreducible polynomial.
The following sources of entropy are used:

 (a) When an interrupt occurs, the high-resolution time stamp is mixed
into the LFSR. This time stamp is credited with heuristically implied
entropy.

 (b) HID event data like the key stroke or the mouse coordinates are
mixed into the LFSR. This data is not credited with entropy by the LRNG.

 (c) Device drivers may provide data that is mixed into the LFSR. This
data is not credited with entropy by the LRNG.

 (d) After the entropy pool is ``read'' by the TRNG, the data
used to seed the TRNG is mixed back into the entropy pool to
stir the pool. This data is not credited with entropy by the LRNG.

Any data provided from user space by either writing to /dev/random,
/dev/urandom or the IOCTL of RNDADDENTROPY on both device files
are always injected into the entropy pool.

In addition, when a hardware random number generator covered by the
Linux kernel HW generator framework wants to deliver random numbers,
it is injected into the entropy pool as well. HW generator noise source
is handled separately from the other noise source due to the fact that
the HW generator framework may decide by itself when to deliver data
whereas the other noise sources always requested for data driven by the
LRNG operation. Similarly any user space provided data is inserted into
the entropy pool.

When the TRNG requires data from the entropy pool, the entire
entropy pool is processed with an SP800-90A section 10.3.1 compliant
hash_df function to generate random numbers.

To speed up the interrupt handling code of the LRNG, the time stamp
collected for an interrupt event is truncated to the 8 least
significant bits. 64 truncated time stamps are concatenated and then
jointly inserted into the LFSR. During boot time, until the fully seeded
stage is reached, each time stamp with its 32 least significant bits is
inserted into the LFSR at the time of arrival.

The LRNG allows the TRNG and secondary DRNG mechanism to be changed
at runtime. Per default, a ChaCha20-based DRNG is used. The ChaCha20-DRNG
implemented for the LRNG is also provided as a stand-alone user space
deterministic random number generator. The LRNG also offers an
SP800-90A DRBG based on the Linux kernel crypto API DRBG implementation.

The DRNG allows two methods of obtaining random data:

* For users requiring random numbers from a seeded and frequently reseeded
secondary DRNG, such as the /dev/urandom, the getrandom system call with
GRND_RANDOM or with a zero flags field, /dev/random, or the in-kernel
get_random_bytes function, the secondary DRNG is accessed directly by
invoking its generate function. This generate function complies with the
generate function discussed in SP800-90A.

* Users requiring random data that contains information theoretical
entropy, such as for seeding other DRNGs also use the TRNG's
generate function via the /dev/random device file and the getrandom
system call when invoked with GRND_TRUERANDOM. The difference to the
/dev/urandom handling is that:

 1. each TRNG generate request is limited to the amount of entropy
the of the DRNG was seeded with, and

 2. each TRNG generate request is preceded by a reseeding of the
DRNG to implement a TRNG / a DRNG with prediction resistance.

The processing of entropic data from the noise source before injecting
them into the TRNG is performed with the following mathematical
operations:

1. LFSR: The 8 least significant bits of the time stamp data received
from the interrupts are processed with an LFSR. That LFSR is implemented
identically to the LSFR used in the existing /dev/random implementation
except that it is capable of processing an entire word and that a
different polynomial is used. The reason for the different polynomial
is performance in a performance sensitive code section, the interrupt
handler. The chosen polynomials have 4 taps. Also, this LFSR-approach
is used in the OpenBSD /dev/random equivalent.

2. Concatenation: The temporary seed buffer used to seed the TRNG is
a concatenation of parts of the entropy pool data, and the CPU noise
source output.

The TRNG always tries to seed itself with 256 bits of entropy,
except during boot. In any case, if the noise sources cannot deliver
that amount, the available entropy is used and the TRNG keeps
track on how much entropy it was seeded with. The entropy implied by
the LRNG available in the entropy pool may be too conservative.
To ensure that during boot time all available entropy from the entropy
pool is transferred to the TRNG, the hash_df function always
generates 256 data bits during boot to seed the TRNG. Yet, the
TRNG entropy estimate is only increased by the amount of entropy the
LRNG assumes to be present in that data. During boot, the TRNG
is seeded as follows:

1. The DRNG is reseeded from the entropy pool and potentially the fast
noise sources if the entropy pool has collected at least 32 bits of
entropy from the interrupt noise source. The goal of this step is to
ensure that the primary and secondary DRNG receive some initial entropy
as early as possible. In addition it receives the entropy available from
the fast noise sources.

2. The DRNG is reseeded from the entropy pool and potentially the fast
noise sources if all noise sources collectively can provide at least
128 bits of entropy.

3. The DRNG is reseeded from the entropy pool and potentially the fast
noise sources if all noise sources collectivel can provide at least 256
bits.

At the time of the reseeding steps, the DRNG requests as much entropy as
is available in order to skip certain steps and reach the seeding level
of 256 bits. This may imply that one or more of the aforementioned steps
are skipped.

In all listed steps, the secondary DRNG is (re)seeded with a number of
random bytes from the TRNG that is equal to the amount of
entropy the TRNG was seeded with. This means that when the
TRNG is seeded with 128 or 256 bits of entropy, the secondary
DRNG is seeded with that amount of entropy as well. There is only one
exception to that rule: during initialization before the seed level of
128 bits is reached, a random number with 128 bit is generated by the
TRNG to seed the secondary DRNG.

Before the TRNG is seeded with 256 bits of entropy in step 3,
requests of random data from /dev/random are not processed.

At runtime, the TRNG delivers only random bytes equal to the
entropy amount it was seeded with. E.g. if the TRNG was seeded
with 128 bits of entropy, it will return only 128 bits of random data.
Subsequent requests for random data are only fulfilled after a
reseeding operation of the TRNG.

The TRNG will always require that all entropy sources collectively
can deliver at least as many entropy bits as configured with
/proc/sys/kernel/random/read_wakeup_threshold, i.e. per default 129 bits
(128 bits of entropy for seeding plus one bit of entropy that is lost
with the post processing as defined in SP800-90B).

The secondary DRNG operates as deterministic random number generator with
the following properties:

* The maximum number of random bytes that can be generated with one
DRNG generate operation is limited to 4096 bytes. When longer random
numbers are requested, multiple DRNG generate operations are performed.
The ChaCha20 DRNG as well as the SP800-90A DRBGs implement an update of
their state after completing a generate request for backtracking
resistance.

* The secondary DRNG is reseeded with whatever entropy is available –
in the worst case where no additional entropy can be provided by the
noise sources, the DRNG is not re-seeded and continues its operation
to try to reseed again after again the expiry of one of these thresholds:

 - If the last reseeding of the secondary DRNG is more than 600 seconds
   ago, or

 - 2^20 DRNG generate operations are performed, whatever comes first, or

 - the secondary DRNG is forced to reseed before the next generation of
   random numbers if data has been injected into the LRNG by writing data
   into /dev/random or /dev/urandom.

The chosen values prevent high-volume requests from user space to cause
frequent reseeding operations which drag down the performance of the
DRNG.

When the secondary DRNG requests a reseeding from the TRNG and
the TRNG pulls from the entropy pool, an emergency entropy level
of 512 bits of entropy is left in the entropy pool. This emergency
entropy is provided to serve getrandom(GRND_TRUERANDOM) even
when called by a process possessing CAP_SYS_ADMIN while /dev/urandom
is stressed.

To ensure that unprivileged users cannot deplete the entropy pool
completely, getrandom(GRND_TRUERANDOM) will leave an emergency level
of 1024 bits of entropy in the entropy pool when it is called by
an unprivileged application. This allows the secondary DRNGs to be
seeded twice with full entropy.

With the automatic reseeding after 600 seconds, the LRNG is triggered
to reseed itself before the first request after a suspend that put the
hardware to sleep for longer than 600 seconds.

The TRNG may not be compiled. In this case, the aforementioned
statements covering the TRNG are not applicable. The secondary DRNG is
seeded directly from the entropy pool just like the TRNG would have been
seeded.

The LRNG has the following properties:

* internal noise source: interrupts timing with fast boot time seeding

* 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().

* lockless LFSR to collect raw entropy

* use of standalone ChaCha20 based RNG with the option to use a
  different DRNG selectable at compile time

* "atomic" seeding of secondary DRBG to ensure full entropy transport

* instantiate one DRNG per NUMA node

* support for runtime switchable output DRNGs

* support for TRNG deactivation: The LRNG supports the compile-time
deactivation of the TRNG (i.e. deactivating
getrandom(GRND_TRUERANDOM)).

* use of only well-defined entropy-preserving operations to collect,
compress and forward entropy: concatenation, LFSR, SP800-90A hash_df
function

* compile-time selectable entropy pool size: the choice also
uses the applicable LFSR polynomial to maintain the entropy pool
size

Further details including the rationale for the design choices and
properties of the LRNG together with testing is provided at [1].
In addition, the documentation explains the conducted regression
tests to verify that the LRNG is API and ABI compatible with the
existing /dev/random implementation.

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

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Mathematical aspects Reviewed-by: "Peter, Matthias" <matthias.peter@bsi.bund.de>
Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 MAINTAINERS                         |   7 +
 drivers/char/Kconfig                |   2 +
 drivers/char/Makefile               |   9 +-
 drivers/char/lrng/Kconfig           |  55 +++
 drivers/char/lrng/Makefile          |   9 +
 drivers/char/lrng/lrng_archrandom.c |  92 ++++
 drivers/char/lrng/lrng_aux.c        | 148 ++++++
 drivers/char/lrng/lrng_chacha20.c   | 329 ++++++++++++++
 drivers/char/lrng/lrng_interfaces.c | 666 +++++++++++++++++++++++++++
 drivers/char/lrng/lrng_internal.h   | 311 +++++++++++++
 drivers/char/lrng/lrng_pool.c       | 671 ++++++++++++++++++++++++++++
 drivers/char/lrng/lrng_sdrng.c      | 420 +++++++++++++++++
 drivers/char/lrng/lrng_sw_noise.c   | 144 ++++++
 include/linux/lrng.h                |  71 +++
 14 files changed, 2933 insertions(+), 1 deletion(-)
 create mode 100644 drivers/char/lrng/Kconfig
 create mode 100644 drivers/char/lrng/Makefile
 create mode 100644 drivers/char/lrng/lrng_archrandom.c
 create mode 100644 drivers/char/lrng/lrng_aux.c
 create mode 100644 drivers/char/lrng/lrng_chacha20.c
 create mode 100644 drivers/char/lrng/lrng_interfaces.c
 create mode 100644 drivers/char/lrng/lrng_internal.h
 create mode 100644 drivers/char/lrng/lrng_pool.c
 create mode 100644 drivers/char/lrng/lrng_sdrng.c
 create mode 100644 drivers/char/lrng/lrng_sw_noise.c
 create mode 100644 include/linux/lrng.h

diff --git a/MAINTAINERS b/MAINTAINERS
index e4f170d8bc29..851d3c2ea1af 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9490,6 +9490,13 @@ F:	Documentation/core-api/atomic_ops.rst
 F:	Documentation/core-api/refcount-vs-atomic.rst
 F:	Documentation/memory-barriers.txt
 
+LINUX RANDOM NUMBER GENERATOR (LRNG) DRIVER
+M:	Stephan Mueller <smueller@chronox.de>
+S:	Maintained
+W:	https://www.chronox.de/lrng.html
+F:	drivers/char/lrng/*
+F:	include/linux/lrng.h
+
 LIS3LV02D ACCELEROMETER DRIVER
 M:	Eric Piel <eric.piel@tremplin-utc.net>
 S:	Maintained
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index df0fc997dc3e..cebb3a62c2ca 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -535,6 +535,8 @@ config ADI
 	  and SSM (Silicon Secured Memory).  Intended consumers of this
 	  driver include crash and makedumpfile.
 
+source "drivers/char/lrng/Kconfig"
+
 endmenu
 
 config RANDOM_TRUST_CPU
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 7c5ea6f9df14..46ede09fd6d3 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -3,7 +3,14 @@
 # Makefile for the kernel character device drivers.
 #
 
-obj-y				+= mem.o random.o
+obj-y				+= mem.o
+
+ifeq ($(CONFIG_LRNG),y)
+  obj-y				+= lrng/
+else
+  obj-y				+= random.o
+endif
+
 obj-$(CONFIG_TTY_PRINTK)	+= ttyprintk.o
 obj-y				+= misc.o
 obj-$(CONFIG_ATARI_DSP56K)	+= dsp56k.o
diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
new file mode 100644
index 000000000000..1ba10fd421f3
--- /dev/null
+++ b/drivers/char/lrng/Kconfig
@@ -0,0 +1,55 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Linux Random Number Generator configuration
+#
+
+menuconfig LRNG
+	bool "Linux Random Number Generator"
+	help
+	  The Linux Random Number Generator (LRNG) is the replacement
+	  of the existing /dev/random provided with drivers/char/random.c.
+	  It generates entropy from different noise sources and
+	  delivers significant entropy during boot.
+
+if LRNG
+
+choice
+	prompt "LRNG Entropy Pool Size"
+	default LRNG_POOL_SIZE_4096
+	help
+	  Select the size of the LRNG entropy pool. The size of the
+	  entropy pool is relevant for the amount of entropy that
+	  the LRNG can maintain as a maximum. The larger the size
+	  of the entropy pool is the more entropy can be maintained
+	  but the less often older entropic values are overwritten
+	  with new entropy.
+
+	config LRNG_POOL_SIZE_4096
+		bool "4096 bits (default)"
+
+	config LRNG_POOL_SIZE_8192
+		bool "8192 bits"
+
+	config LRNG_POOL_SIZE_16384
+		bool "16384 bits"
+
+	config LRNG_POOL_SIZE_32768
+		bool "32768 bits"
+
+	config LRNG_POOL_SIZE_65536
+		bool "65536 bits"
+
+	config LRNG_POOL_SIZE_131072
+		bool "131072 bits"
+endchoice
+
+config LRNG_POOL_SIZE
+	int
+	default 0 if LRNG_POOL_SIZE_4096
+	default 1 if LRNG_POOL_SIZE_8192
+	default 2 if LRNG_POOL_SIZE_16384
+	default 3 if LRNG_POOL_SIZE_32768
+	default 4 if LRNG_POOL_SIZE_65536
+	default 5 if LRNG_POOL_SIZE_131072
+
+endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
new file mode 100644
index 000000000000..2761623715d2
--- /dev/null
+++ b/drivers/char/lrng/Makefile
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for the Linux Random Number Generator.
+#
+
+obj-y				+= lrng_pool.o lrng_aux.o \
+				   lrng_sw_noise.o lrng_archrandom.o \
+				   lrng_sdrng.o lrng_chacha20.o \
+				   lrng_interfaces.o \
diff --git a/drivers/char/lrng/lrng_archrandom.c b/drivers/char/lrng/lrng_archrandom.c
new file mode 100644
index 000000000000..e03dc57c56f6
--- /dev/null
+++ b/drivers/char/lrng/lrng_archrandom.c
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG Fast Noise Source: CPU-based noise source
+ *
+ * Copyright (C) 2016 - 2019, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/random.h>
+
+#include "lrng_internal.h"
+
+/*
+ * Estimated entropy of data is a 32th of LRNG_DRNG_SECURITY_STRENGTH_BITS.
+ * As we have no ability to review the implementation of those noise sources,
+ * it is prudent to have a conservative estimate here.
+ */
+#define LRNG_ARCHRANDOM_DEFAULT_STRENGTH (LRNG_DRNG_SECURITY_STRENGTH_BITS>>5)
+#define LRNG_ARCHRANDOM_TRUST_CPU_STRENGTH LRNG_DRNG_SECURITY_STRENGTH_BITS
+#ifdef CONFIG_RANDOM_TRUST_CPU
+static u32 archrandom = LRNG_ARCHRANDOM_TRUST_CPU_STRENGTH;
+#else
+static u32 archrandom = LRNG_ARCHRANDOM_DEFAULT_STRENGTH;
+#endif
+module_param(archrandom, uint, 0644);
+MODULE_PARM_DESC(archrandom, "Entropy in bits of 256 data bits from CPU noise "
+			     "source (e.g. RDRAND)");
+
+static int __init lrng_parse_trust_cpu(char *arg)
+{
+	int ret;
+	bool trust_cpu = false;
+
+	ret = kstrtobool(arg, &trust_cpu);
+	if (ret)
+		return ret;
+
+	if (trust_cpu)
+		archrandom = LRNG_ARCHRANDOM_TRUST_CPU_STRENGTH;
+	else
+		archrandom = LRNG_ARCHRANDOM_DEFAULT_STRENGTH;
+
+	return 0;
+}
+early_param("random.trust_cpu", lrng_parse_trust_cpu);
+
+/**
+ * Get CPU noise source entropy
+ *
+ * @outbuf: buffer to store entropy of size LRNG_DRNG_SECURITY_STRENGTH_BYTES
+ * @return: > 0 on success where value provides the added entropy in bits
+ *	    0 if no fast source was available
+ */
+u32 lrng_get_arch(u8 *outbuf)
+{
+	u32 i, ent_bits = archrandom;
+
+	/* operate on full blocks */
+	BUILD_BUG_ON(LRNG_DRNG_SECURITY_STRENGTH_BYTES % sizeof(unsigned long));
+	/* ensure we have aligned buffers */
+	BUILD_BUG_ON(LRNG_KCAPI_ALIGN % sizeof(unsigned long));
+
+	if (!ent_bits)
+		return 0;
+
+	for (i = 0; i < LRNG_DRNG_SECURITY_STRENGTH_BYTES;
+	     i += sizeof(unsigned long)) {
+		if (!arch_get_random_seed_long((unsigned long *)(outbuf + i)) &&
+		    !arch_get_random_long((unsigned long *)(outbuf + i))) {
+			archrandom = 0;
+			return 0;
+		}
+	}
+
+	/* Obtain entropy statement -- cap entropy to buffer size in bits */
+	ent_bits = min_t(u32, ent_bits, LRNG_DRNG_SECURITY_STRENGTH_BITS);
+	pr_debug("obtained %u bits of entropy from CPU RNG noise source\n",
+		 ent_bits);
+	return ent_bits;
+}
+
+u32 lrng_slow_noise_req_entropy(u32 required_entropy_bits)
+{
+	u32 arch_ent_bits = min_t(u32, archrandom,
+				  LRNG_DRNG_SECURITY_STRENGTH_BITS);
+	u32 fast_noise_entropy = arch_ent_bits + lrng_jent_entropylevel();
+
+	if (fast_noise_entropy > required_entropy_bits)
+		return 0;
+	return (required_entropy_bits - fast_noise_entropy);
+}
diff --git a/drivers/char/lrng/lrng_aux.c b/drivers/char/lrng/lrng_aux.c
new file mode 100644
index 000000000000..de2904523ea2
--- /dev/null
+++ b/drivers/char/lrng/lrng_aux.c
@@ -0,0 +1,148 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG auxiliary interfaces
+ *
+ * Copyright (C) 2019 Stephan Mueller <smueller@chronox.de>
+ * Copyright (C) 2017 Jason A. Donenfeld <Jason@zx2c4.com>. All
+ * Rights Reserved.
+ * Copyright (C) 2016 Jason Cooper <jason@lakedaemon.net>
+ */
+
+#include <linux/mm.h>
+#include <linux/random.h>
+
+#include "lrng_internal.h"
+
+struct batched_entropy {
+	union {
+		u64 entropy_u64[LRNG_DRNG_BLOCKSIZE / sizeof(u64)];
+		u32 entropy_u32[LRNG_DRNG_BLOCKSIZE / sizeof(u32)];
+	};
+	unsigned int position;
+	spinlock_t batch_lock;
+};
+
+/*
+ * Get a random word for internal kernel use only. The quality of the random
+ * number is either as good as RDRAND or as good as /dev/urandom, with the
+ * goal of being quite fast and not depleting entropy.
+ */
+static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_u64) = {
+	.batch_lock	= __SPIN_LOCK_UNLOCKED(batched_entropy_u64.lock),
+};
+
+u64 get_random_u64(void)
+{
+	u64 ret;
+	unsigned long flags;
+	struct batched_entropy *batch;
+
+#if BITS_PER_LONG == 64
+	if (arch_get_random_long((unsigned long *)&ret))
+		return ret;
+#else
+	if (arch_get_random_long((unsigned long *)&ret) &&
+	    arch_get_random_long((unsigned long *)&ret + 1))
+		return ret;
+#endif
+
+	lrng_debug_report_seedlevel("get_random_u64");
+
+	batch = raw_cpu_ptr(&batched_entropy_u64);
+	spin_lock_irqsave(&batch->batch_lock, flags);
+	if (batch->position % ARRAY_SIZE(batch->entropy_u64) == 0) {
+		lrng_sdrng_get_atomic((u8 *)batch->entropy_u64,
+				      LRNG_DRNG_BLOCKSIZE);
+		batch->position = 0;
+	}
+	ret = batch->entropy_u64[batch->position++];
+	spin_unlock_irqrestore(&batch->batch_lock, flags);
+	return ret;
+}
+EXPORT_SYMBOL(get_random_u64);
+
+static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_u32) = {
+	.batch_lock	= __SPIN_LOCK_UNLOCKED(batched_entropy_u32.lock),
+};
+
+u32 get_random_u32(void)
+{
+	u32 ret;
+	unsigned long flags;
+	struct batched_entropy *batch;
+
+	if (arch_get_random_int(&ret))
+		return ret;
+
+	lrng_debug_report_seedlevel("get_random_u32");
+
+	batch = raw_cpu_ptr(&batched_entropy_u32);
+	spin_lock_irqsave(&batch->batch_lock, flags);
+	if (batch->position % ARRAY_SIZE(batch->entropy_u32) == 0) {
+		lrng_sdrng_get_atomic((u8 *)batch->entropy_u32,
+				      LRNG_DRNG_BLOCKSIZE);
+		batch->position = 0;
+	}
+	ret = batch->entropy_u32[batch->position++];
+	spin_unlock_irqrestore(&batch->batch_lock, flags);
+	return ret;
+}
+EXPORT_SYMBOL(get_random_u32);
+
+/*
+ * It's important to invalidate all potential batched entropy that might
+ * be stored before the crng is initialized, which we can do lazily by
+ * simply resetting the counter to zero so that it's re-extracted on the
+ * next usage.
+ */
+void invalidate_batched_entropy(void)
+{
+	int cpu;
+	unsigned long flags;
+
+	for_each_possible_cpu(cpu) {
+		struct batched_entropy *batched_entropy;
+
+		batched_entropy = per_cpu_ptr(&batched_entropy_u32, cpu);
+		spin_lock_irqsave(&batched_entropy->batch_lock, flags);
+		batched_entropy->position = 0;
+		spin_unlock(&batched_entropy->batch_lock);
+
+		batched_entropy = per_cpu_ptr(&batched_entropy_u64, cpu);
+		spin_lock(&batched_entropy->batch_lock);
+		batched_entropy->position = 0;
+		spin_unlock_irqrestore(&batched_entropy->batch_lock, flags);
+	}
+}
+
+/**
+ * randomize_page - Generate a random, page aligned address
+ * @start:	The smallest acceptable address the caller will take.
+ * @range:	The size of the area, starting at @start, within which the
+ *		random address must fall.
+ *
+ * If @start + @range would overflow, @range is capped.
+ *
+ * NOTE: Historical use of randomize_range, which this replaces, presumed that
+ * @start was already page aligned.  We now align it regardless.
+ *
+ * Return: A page aligned address within [start, start + range).  On error,
+ * @start is returned.
+ */
+unsigned long randomize_page(unsigned long start, unsigned long range)
+{
+	if (!PAGE_ALIGNED(start)) {
+		range -= PAGE_ALIGN(start) - start;
+		start = PAGE_ALIGN(start);
+	}
+
+	if (start > ULONG_MAX - range)
+		range = ULONG_MAX - start;
+
+	range >>= PAGE_SHIFT;
+
+	if (range == 0)
+		return start;
+
+	return start + (get_random_long() % range << PAGE_SHIFT);
+}
diff --git a/drivers/char/lrng/lrng_chacha20.c b/drivers/char/lrng/lrng_chacha20.c
new file mode 100644
index 000000000000..439b449b3f3e
--- /dev/null
+++ b/drivers/char/lrng/lrng_chacha20.c
@@ -0,0 +1,329 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * Backend for the LRNG providing the cryptographic primitives using
+ * ChaCha20 cipher implementations.
+ *
+ * Copyright (C) 2016 - 2019, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <crypto/chacha.h>
+#include <linux/cryptohash.h>
+#include <linux/lrng.h>
+#include <linux/random.h>
+#include <linux/slab.h>
+
+#include "lrng_internal.h"
+
+/******************************* ChaCha20 DRNG *******************************/
+
+/* State according to RFC 7539 section 2.3 */
+struct chacha20_block {
+	u32 constants[4];
+#define CHACHA_KEY_SIZE_WORDS (CHACHA_KEY_SIZE / sizeof(u32))
+	union {
+		u32 u[CHACHA_KEY_SIZE_WORDS];
+		u8  b[CHACHA_KEY_SIZE];
+	} key;
+	u32 counter;
+	u32 nonce[3];
+};
+
+#define CHACHA_BLOCK_WORDS	(CHACHA_BLOCK_SIZE / sizeof(u32))
+
+struct chacha20_state {
+	struct chacha20_block block;
+};
+
+/*
+ * Have two static memory blocks for two ChaCha20 DRNG instances (the primary
+ * and the secondary DRNG) to avoid calling kmalloc too early in the boot cycle.
+ * for subsequent allocation requests, such as per-NUMA-node DRNG instances,
+ * kmalloc will be used.
+ */
+struct chacha20_state primary_chacha20;
+struct chacha20_state secondary_chacha20;
+
+/**
+ * Update of the ChaCha20 state by either using an unused buffer part or by
+ * generating one ChaCha20 block which is half of the state of the ChaCha20.
+ * The block is XORed into the key part of the state. This shall ensure
+ * backtracking resistance as well as a proper mix of the ChaCha20 state once
+ * the key is injected.
+ */
+static void lrng_chacha20_update(struct chacha20_state *chacha20_state,
+				 u32 *buf, u32 used_words)
+{
+	struct chacha20_block *chacha20 = &chacha20_state->block;
+	u32 i, tmp[CHACHA_BLOCK_WORDS];
+
+	BUILD_BUG_ON(sizeof(struct chacha20_block) != CHACHA_BLOCK_SIZE);
+	BUILD_BUG_ON(CHACHA_BLOCK_SIZE != 2 * CHACHA_KEY_SIZE);
+
+	if (used_words > CHACHA_KEY_SIZE_WORDS) {
+		chacha20_block(&chacha20->constants[0], (u8 *)tmp);
+		for (i = 0; i < CHACHA_KEY_SIZE_WORDS; i++)
+			chacha20->key.u[i] ^= tmp[i];
+		memzero_explicit(tmp, sizeof(tmp));
+	} else {
+		for (i = 0; i < CHACHA_KEY_SIZE_WORDS; i++)
+			chacha20->key.u[i] ^= buf[i + used_words];
+	}
+
+	/* Deterministic increment of nonce as required in RFC 7539 chapter 4 */
+	chacha20->nonce[0]++;
+	if (chacha20->nonce[0] == 0)
+		chacha20->nonce[1]++;
+	if (chacha20->nonce[1] == 0)
+		chacha20->nonce[2]++;
+
+	/* Leave counter untouched as it is start value is undefined in RFC */
+}
+
+/**
+ * Seed the ChaCha20 DRNG by injecting the input data into the key part of
+ * the ChaCha20 state. If the input data is longer than the ChaCha20 key size,
+ * perform a ChaCha20 operation after processing of key size input data.
+ * This operation shall spread out the entropy into the ChaCha20 state before
+ * new entropy is injected into the key part.
+ */
+static int lrng_cc20_drng_seed_helper(void *drng, const u8 *inbuf, u32 inbuflen)
+{
+	struct chacha20_state *chacha20_state = (struct chacha20_state *)drng;
+	struct chacha20_block *chacha20 = &chacha20_state->block;
+
+	while (inbuflen) {
+		u32 i, todo = min_t(u32, inbuflen, CHACHA_KEY_SIZE);
+
+		for (i = 0; i < todo; i++)
+			chacha20->key.b[i] ^= inbuf[i];
+
+		/* Break potential dependencies between the inbuf key blocks */
+		lrng_chacha20_update(chacha20_state, NULL,
+				     CHACHA_BLOCK_WORDS);
+		inbuf += todo;
+		inbuflen -= todo;
+	}
+
+	return 0;
+}
+
+/**
+ * Chacha20 DRNG generation of random numbers: the stream output of ChaCha20
+ * is the random number. After the completion of the generation of the
+ * stream, the entire ChaCha20 state is updated.
+ *
+ * Note, as the ChaCha20 implements a 32 bit counter, we must ensure
+ * that this function is only invoked for at most 2^32 - 1 ChaCha20 blocks
+ * before a reseed or an update happens. This is ensured by the variable
+ * outbuflen which is a 32 bit integer defining the number of bytes to be
+ * generated by the ChaCha20 DRNG. At the end of this function, an update
+ * operation is invoked which implies that the 32 bit counter will never be
+ * overflown in this implementation.
+ */
+static int lrng_cc20_drng_generate_helper(void *drng, u8 *outbuf, u32 outbuflen)
+{
+	struct chacha20_state *chacha20_state = (struct chacha20_state *)drng;
+	struct chacha20_block *chacha20 = &chacha20_state->block;
+	u32 aligned_buf[CHACHA_BLOCK_WORDS], ret = outbuflen,
+	    used = CHACHA_BLOCK_WORDS;
+	int zeroize_buf = 0;
+
+	while (outbuflen >= CHACHA_BLOCK_SIZE) {
+		chacha20_block(&chacha20->constants[0], outbuf);
+		outbuf += CHACHA_BLOCK_SIZE;
+		outbuflen -= CHACHA_BLOCK_SIZE;
+	}
+
+	if (outbuflen) {
+		chacha20_block(&chacha20->constants[0], (u8 *)aligned_buf);
+		memcpy(outbuf, aligned_buf, outbuflen);
+		used = ((outbuflen + sizeof(aligned_buf[0]) - 1) /
+			sizeof(aligned_buf[0]));
+		zeroize_buf = 1;
+	}
+
+	lrng_chacha20_update(chacha20_state, aligned_buf, used);
+
+	if (zeroize_buf)
+		memzero_explicit(aligned_buf, sizeof(aligned_buf));
+
+	return ret;
+}
+
+/**
+ * ChaCha20 DRNG that provides full strength, i.e. the output is capable
+ * of transporting 1 bit of entropy per data bit, provided the DRNG was
+ * seeded with 256 bits of entropy. This is achieved by folding the ChaCha20
+ * block output of 512 bits in half using XOR.
+ *
+ * Other than the output handling, the implementation is conceptually
+ * identical to lrng_drng_generate_helper.
+ */
+static int lrng_cc20_drng_generate_helper_full(void *drng, u8 *outbuf,
+					       u32 outbuflen)
+{
+	struct chacha20_state *chacha20_state = (struct chacha20_state *)drng;
+	struct chacha20_block *chacha20 = &chacha20_state->block;
+	u32 aligned_buf[CHACHA_BLOCK_WORDS];
+	u32 ret = outbuflen;
+
+	while (outbuflen >= CHACHA_BLOCK_SIZE) {
+		u32 i;
+
+		chacha20_block(&chacha20->constants[0], outbuf);
+
+		/* fold output in half */
+		for (i = 0; i < (CHACHA_BLOCK_WORDS / 2); i++)
+			outbuf[i] ^= outbuf[i + (CHACHA_BLOCK_WORDS / 2)];
+
+		outbuf += CHACHA_BLOCK_SIZE / 2;
+		outbuflen -= CHACHA_BLOCK_SIZE / 2;
+	}
+
+	while (outbuflen) {
+		u32 i, todo = min_t(u32, CHACHA_BLOCK_SIZE / 2, outbuflen);
+
+		chacha20_block(&chacha20->constants[0], (u8 *)aligned_buf);
+
+		/* fold output in half */
+		for (i = 0; i < (CHACHA_BLOCK_WORDS / 2); i++)
+			aligned_buf[i] ^=
+				aligned_buf[i + (CHACHA_BLOCK_WORDS / 2)];
+
+		memcpy(outbuf, aligned_buf, todo);
+		outbuflen -= todo;
+		outbuf += todo;
+	}
+	memzero_explicit(aligned_buf, sizeof(aligned_buf));
+
+	lrng_chacha20_update(chacha20_state, NULL, CHACHA_BLOCK_WORDS);
+
+	return ret;
+}
+
+void lrng_cc20_init_state(struct chacha20_state *state)
+{
+	struct chacha20_block *chacha20 = &state->block;
+	unsigned long v;
+	u32 i;
+
+	memcpy(&chacha20->constants[0], "expand 32-byte k", 16);
+
+	for (i = 0; i < CHACHA_KEY_SIZE_WORDS; i++) {
+		chacha20->key.u[i] ^= jiffies;
+		chacha20->key.u[i] ^= random_get_entropy();
+		if (arch_get_random_seed_long(&v) || arch_get_random_long(&v))
+			chacha20->key.u[i] ^= v;
+	}
+
+	for (i = 0; i < 3; i++) {
+		chacha20->nonce[i] ^= jiffies;
+		chacha20->nonce[i] ^= random_get_entropy();
+		if (arch_get_random_seed_long(&v) || arch_get_random_long(&v))
+			chacha20->nonce[i] ^= v;
+	}
+
+	pr_info("ChaCha20 core initialized\n");
+}
+
+/**
+ * Allocation of the DRNG state
+ */
+static void *lrng_cc20_drng_alloc(u32 sec_strength)
+{
+	struct chacha20_state *state = NULL;
+
+	if (sec_strength > CHACHA_KEY_SIZE) {
+		pr_err("Security strength of ChaCha20 DRNG (%u bits) lower "
+		       "than requested by LRNG (%u bits)\n",
+			CHACHA_KEY_SIZE * 8, sec_strength * 8);
+		return ERR_PTR(-EINVAL);
+	}
+	if (sec_strength < CHACHA_KEY_SIZE)
+		pr_warn("Security strength of ChaCha20 DRNG (%u bits) higher "
+			"than requested by LRNG (%u bits)\n",
+			CHACHA_KEY_SIZE * 8, sec_strength * 8);
+
+	state = kmalloc(sizeof(struct chacha20_state), GFP_KERNEL);
+	if (!state)
+		return ERR_PTR(-ENOMEM);
+	pr_debug("memory for ChaCha20 core allocated\n");
+
+	lrng_cc20_init_state(state);
+
+	return state;
+}
+
+static void lrng_cc20_drng_dealloc(void *drng)
+{
+	struct chacha20_state *chacha20_state = (struct chacha20_state *)drng;
+
+	if (drng == &primary_chacha20 || drng == &secondary_chacha20) {
+		memzero_explicit(chacha20_state, sizeof(*chacha20_state));
+		pr_debug("static ChaCha20 core zeroized\n");
+		return;
+	}
+
+	pr_debug("ChaCha20 core zeroized and freed\n");
+	kzfree(chacha20_state);
+}
+
+/******************************* Hash Operation *******************************/
+
+static void *lrng_cc20_hash_alloc(const u8 *key, u32 keylen)
+{
+	pr_info("Hash SHA-1 allocated\n");
+	return NULL;
+}
+
+static void lrng_cc20_hash_dealloc(void *hash)
+{
+}
+
+static u32 lrng_cc20_hash_digestsize(void *hash)
+{
+	return (SHA_DIGEST_WORDS * sizeof(u32));
+}
+
+static int lrng_cc20_hash_buffer(void *hash, const u8 *inbuf, u32 inbuflen,
+				 u8 *digest)
+{
+	u32 i;
+	u32 workspace[SHA_WORKSPACE_WORDS];
+
+	WARN_ON(inbuflen % (SHA_WORKSPACE_WORDS * sizeof(u32)));
+
+	for (i = 0; i < inbuflen; i += (SHA_WORKSPACE_WORDS * sizeof(u32)))
+		sha_transform((u32 *)digest, (inbuf + i), workspace);
+	memzero_explicit(workspace, sizeof(workspace));
+
+	return 0;
+}
+
+static const char *lrng_cc20_drng_name(void)
+{
+	const char *cc20_drng_name = "ChaCha20 DRNG";
+	return cc20_drng_name;
+}
+
+static const char *lrng_cc20_hash_name(void)
+{
+	const char *cc20_hash_name = "SHA-1";
+	return cc20_hash_name;
+}
+
+const struct lrng_crypto_cb lrng_cc20_crypto_cb = {
+	.lrng_drng_name			= lrng_cc20_drng_name,
+	.lrng_hash_name			= lrng_cc20_hash_name,
+	.lrng_drng_alloc		= lrng_cc20_drng_alloc,
+	.lrng_drng_dealloc		= lrng_cc20_drng_dealloc,
+	.lrng_drng_seed_helper		= lrng_cc20_drng_seed_helper,
+	.lrng_drng_generate_helper	= lrng_cc20_drng_generate_helper,
+	.lrng_drng_generate_helper_full	= lrng_cc20_drng_generate_helper_full,
+	.lrng_hash_alloc		= lrng_cc20_hash_alloc,
+	.lrng_hash_dealloc		= lrng_cc20_hash_dealloc,
+	.lrng_hash_digestsize		= lrng_cc20_hash_digestsize,
+	.lrng_hash_buffer		= lrng_cc20_hash_buffer,
+};
diff --git a/drivers/char/lrng/lrng_interfaces.c b/drivers/char/lrng/lrng_interfaces.c
new file mode 100644
index 000000000000..39fc3282843e
--- /dev/null
+++ b/drivers/char/lrng/lrng_interfaces.c
@@ -0,0 +1,666 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG User and kernel space interfaces
+ *
+ * Copyright (C) 2016 - 2019, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/freezer.h>
+#include <linux/fs.h>
+#include <linux/genhd.h>
+#include <linux/kthread.h>
+#include <linux/poll.h>
+#include <linux/preempt.h>
+#include <linux/random.h>
+#include <linux/slab.h>
+#include <linux/syscalls.h>
+#include <linux/timex.h>
+
+#include "lrng_internal.h"
+
+/*
+ * The minimum number of bits of entropy before we wake up a read on
+ * /dev/random.
+ */
+u32 lrng_read_wakeup_bits = LRNG_MIN_SEED_ENTROPY_BITS +
+			    LRNG_CONDITIONING_ENTROPY_LOSS;
+
+/*
+ * If the entropy count falls under this number of bits, then we
+ * should wake up processes which are selecting or polling on write
+ * access to /dev/random.
+ */
+u32 lrng_write_wakeup_bits = LRNG_EMERG_ENTROPY +
+			     2 * LRNG_DRNG_SECURITY_STRENGTH_BITS;
+
+static LIST_HEAD(lrng_ready_list);
+static DEFINE_SPINLOCK(lrng_ready_list_lock);
+
+static DECLARE_WAIT_QUEUE_HEAD(lrng_read_wait);
+static DECLARE_WAIT_QUEUE_HEAD(lrng_write_wait);
+static DECLARE_WAIT_QUEUE_HEAD(lrng_init_wait);
+static struct fasync_struct *fasync;
+
+struct ctl_table random_table[];
+/********************************** Helper ***********************************/
+
+/* Is the primary DRNG seed level too low? */
+static inline bool lrng_need_entropy(void)
+{
+	return (lrng_avail_entropy() < lrng_write_wakeup_bits);
+}
+
+/* Is the entropy pool filled for TRNG pull or DRNG fully seeded? */
+static inline bool lrng_have_entropy_full(void)
+{
+	return (lrng_avail_entropy() >= lrng_read_wakeup_bits);
+}
+
+static inline bool lrng_have_entropy_full_trng(void)
+{
+	return (lrng_avail_entropy() >= lrng_read_wakeup_bits +
+					lrng_trng_retain());
+}
+
+void lrng_reader_wakeup(void)
+{
+	if (lrng_have_entropy_full() && wq_has_sleeper(&lrng_read_wait)) {
+		wake_up_interruptible(&lrng_read_wait);
+		kill_fasync(&fasync, SIGIO, POLL_IN);
+	}
+}
+
+void lrng_writer_wakeup(void)
+{
+	if (lrng_need_entropy() && wq_has_sleeper(&lrng_write_wait)) {
+		wake_up_interruptible(&lrng_write_wait);
+		kill_fasync(&fasync, SIGIO, POLL_OUT);
+	}
+}
+
+void lrng_init_wakeup(void)
+{
+	wake_up_all(&lrng_init_wait);
+}
+
+/**
+ * Ping all kernel internal callers waiting until the DRNG is fully
+ * seeded that the DRNG is now fully seeded.
+ *
+ * When the SP800-90B testing is enabled, the ping only happens if the SP800-90B
+ * startup health tests are completed. This implies that kernel internal
+ * callers always have an SP800-90B compliant noise source when being
+ * pinged.
+ */
+void lrng_process_ready_list(void)
+{
+	unsigned long flags;
+	struct random_ready_callback *rdy, *tmp;
+
+	if (!lrng_sp80090b_startup_complete())
+		return;
+
+	spin_lock_irqsave(&lrng_ready_list_lock, flags);
+	list_for_each_entry_safe(rdy, tmp, &lrng_ready_list, list) {
+		struct module *owner = rdy->owner;
+
+		list_del_init(&rdy->list);
+		rdy->func(rdy);
+		module_put(owner);
+	}
+	spin_unlock_irqrestore(&lrng_ready_list_lock, flags);
+}
+
+void lrng_debug_report_seedlevel(const char *name)
+{
+#ifdef CONFIG_WARN_ALL_UNSEEDED_RANDOM
+	static void *previous = NULL;
+	void *caller = (void *) _RET_IP_;
+
+	if (READ_ONCE(previous) == caller)
+		return;
+
+	if (!lrng_state_min_seeded())
+		pr_notice("%pS %s called without reaching mimimally seeded "
+			  "level (available entropy %u)\n", caller, name,
+			  lrng_avail_entropy());
+
+	WRITE_ONCE(previous, caller);
+#endif
+}
+
+/************************ LRNG kernel input interfaces ************************/
+
+/**
+ * Interface for in-kernel drivers of true hardware RNGs.
+ * Those devices may produce endless random bits and will be throttled
+ * when our pool is full.
+ *
+ * @buffer: buffer holding the entropic data from HW noise sources to be used to
+ *	    (re)seed the DRNG.
+ * @count: length of buffer
+ * @entropy_bits: amount of entropy in buffer (value is in bits)
+ */
+void add_hwgenerator_randomness(const char *buffer, size_t count,
+				size_t entropy_bits)
+{
+	/* DRNG is not yet online */
+	if (!lrng_get_available())
+		return;
+	/*
+	 * Suspend writing if we are fully loaded with entropy.
+	 * We'll be woken up again once below lrng_write_wakeup_thresh,
+	 * or when the calling thread is about to terminate.
+	 */
+	wait_event_interruptible(lrng_write_wait, lrng_need_entropy() ||
+						  kthread_should_stop() ||
+						  freezing(current));
+	lrng_pool_lfsr_nonaligned(buffer, count);
+	lrng_pool_add_entropy(entropy_bits);
+}
+EXPORT_SYMBOL_GPL(add_hwgenerator_randomness);
+
+/* Handle random seed passed by bootloader.
+ * If the seed is trustworthy, it would be regarded as hardware RNGs. Otherwise
+ * it would be regarded as device data.
+ * The decision is controlled by CONFIG_RANDOM_TRUST_BOOTLOADER.
+ */
+void add_bootloader_randomness(const void *buf, unsigned int size)
+{
+	if (IS_ENABLED(CONFIG_RANDOM_TRUST_BOOTLOADER))
+		add_hwgenerator_randomness(buf, size, size * 8);
+	else
+		add_device_randomness(buf, size);
+}
+EXPORT_SYMBOL_GPL(add_bootloader_randomness);
+
+/**
+ * Callback for HID layer -- use the HID event values to stir the entropy pool
+ */
+void add_input_randomness(unsigned int type, unsigned int code,
+			  unsigned int value)
+{
+	static unsigned char last_value;
+
+	/* ignore autorepeat and the like */
+	if (value == last_value)
+		return;
+
+	last_value = value;
+
+	lrng_pool_lfsr_u32((type << 4) ^ code ^ (code >> 4) ^ value);
+}
+EXPORT_SYMBOL_GPL(add_input_randomness);
+
+/*
+ * Add device- or boot-specific data to the input pool to help
+ * initialize it.
+ *
+ * None of this adds any entropy; it is meant to avoid the problem of
+ * the entropy pool having similar initial state across largely
+ * identical devices.
+ */
+void add_device_randomness(const void *buf, unsigned int size)
+{
+	lrng_pool_lfsr_nonaligned((u8 *)buf, size);
+	lrng_pool_lfsr_u32(random_get_entropy());
+	lrng_pool_lfsr_u32(jiffies);
+}
+EXPORT_SYMBOL(add_device_randomness);
+
+#ifdef CONFIG_BLOCK
+void rand_initialize_disk(struct gendisk *disk) { }
+void add_disk_randomness(struct gendisk *disk) { }
+EXPORT_SYMBOL(add_disk_randomness);
+#endif
+
+/**
+ * Delete a previously registered readiness callback function.
+ */
+void del_random_ready_callback(struct random_ready_callback *rdy)
+{
+	unsigned long flags;
+	struct module *owner = NULL;
+
+	spin_lock_irqsave(&lrng_ready_list_lock, flags);
+	if (!list_empty(&rdy->list)) {
+		list_del_init(&rdy->list);
+		owner = rdy->owner;
+	}
+	spin_unlock_irqrestore(&lrng_ready_list_lock, flags);
+
+	module_put(owner);
+}
+EXPORT_SYMBOL(del_random_ready_callback);
+
+/**
+ * Add a callback function that will be invoked when the DRNG is fully seeded.
+ *
+ * @return: 0 if callback is successfully added
+ *          -EALREADY if pool is already initialised (callback not called)
+ *	    -ENOENT if module for callback is not alive
+ */
+int add_random_ready_callback(struct random_ready_callback *rdy)
+{
+	struct module *owner;
+	unsigned long flags;
+	int err = -EALREADY;
+
+	if (likely(lrng_state_min_seeded()))
+		return err;
+
+	owner = rdy->owner;
+	if (!try_module_get(owner))
+		return -ENOENT;
+
+	spin_lock_irqsave(&lrng_ready_list_lock, flags);
+	if (lrng_state_min_seeded())
+		goto out;
+
+	owner = NULL;
+
+	list_add(&rdy->list, &lrng_ready_list);
+	err = 0;
+
+out:
+	spin_unlock_irqrestore(&lrng_ready_list_lock, flags);
+
+	module_put(owner);
+
+	return err;
+}
+EXPORT_SYMBOL(add_random_ready_callback);
+
+/*********************** LRNG kernel output interfaces ************************/
+
+/**
+ * Provider of cryptographic strong random numbers for kernel-internal usage.
+ * This function is appropriate for all in-kernel use cases. However,
+ * it will always use the ChaCha20 DRNG.
+ *
+ * @buf: buffer to store the random bytes
+ * @nbytes: size of the buffer
+ */
+void get_random_bytes(void *buf, int nbytes)
+{
+	lrng_sdrng_get_atomic((u8 *)buf, (u32)nbytes);
+	lrng_debug_report_seedlevel("get_random_bytes");
+}
+EXPORT_SYMBOL(get_random_bytes);
+
+/**
+ * Provider of cryptographic strong random numbers for kernel-internal usage.
+ * This function is appropriate only for non-atomic use cases as this
+ * function may sleep. Though, it provides access to the full functionality
+ * of LRNG including the switchable DRNG support, that may support other
+ * DRNGs such as the SP800-90A DRBG.
+ *
+ * @buf: buffer to store the random bytes
+ * @nbytes: size of the buffer
+ */
+void get_random_bytes_full(void *buf, int nbytes)
+{
+	lrng_sdrng_get_sleep((u8 *)buf, (u32)nbytes);
+	lrng_debug_report_seedlevel("get_random_bytes_full");
+}
+EXPORT_SYMBOL(get_random_bytes_full);
+
+/**
+ * Wait for the LRNG to be seeded and thus guaranteed to supply
+ * cryptographically secure random numbers. This applies to: the /dev/urandom
+ * device, the get_random_bytes function, and the get_random_{u32,u64,int,long}
+ * family of functions. Using any of these functions without first calling
+ * this function forfeits the guarantee of security.
+ *
+ * Returns: 0 if the LRNG has been seeded.
+ *          -ERESTARTSYS if the function was interrupted by a signal.
+ */
+int wait_for_random_bytes(void)
+{
+	if (likely(lrng_state_min_seeded()))
+		return 0;
+	return wait_event_interruptible(lrng_init_wait,
+					lrng_state_min_seeded());
+}
+EXPORT_SYMBOL(wait_for_random_bytes);
+
+/**
+ * This function will use the architecture-specific hardware random
+ * number generator if it is available.  The arch-specific hw RNG will
+ * almost certainly be faster than what we can do in software, but it
+ * is impossible to verify that it is implemented securely (as
+ * opposed, to, say, the AES encryption of a sequence number using a
+ * key known by the NSA).  So it's useful if we need the speed, but
+ * only if we're willing to trust the hardware manufacturer not to
+ * have put in a back door.
+ *
+ * @buf: buffer allocated by caller to store the random data in
+ * @nbytes: length of outbuf
+ *
+ * Return number of bytes filled in.
+ */
+int __must_check get_random_bytes_arch(void *buf, int nbytes)
+{
+	u8 *p = buf;
+
+	while (nbytes) {
+		unsigned long v;
+		int chunk = min_t(int, nbytes, sizeof(unsigned long));
+
+		if (!arch_get_random_long(&v))
+			break;
+
+		memcpy(p, &v, chunk);
+		p += chunk;
+		nbytes -= chunk;
+	}
+
+	if (nbytes)
+		lrng_sdrng_get_atomic((u8 *)p, (u32)nbytes);
+
+	return nbytes;
+}
+EXPORT_SYMBOL(get_random_bytes_arch);
+
+/************************ LRNG user output interfaces *************************/
+
+static ssize_t lrng_read_common(char __user *buf, size_t nbytes,
+			int (*lrng_read_random)(u8 *outbuf, u32 outbuflen))
+{
+	ssize_t ret = 0;
+	u8 tmpbuf[LRNG_DRNG_BLOCKSIZE] __aligned(LRNG_KCAPI_ALIGN);
+	u8 *tmp_large = NULL, *tmp = tmpbuf;
+	u32 tmplen = sizeof(tmpbuf);
+
+	if (nbytes == 0)
+		return 0;
+
+	/*
+	 * Satisfy large read requests -- as the common case are smaller
+	 * request sizes, such as 16 or 32 bytes, avoid a kmalloc overhead for
+	 * those by using the stack variable of tmpbuf.
+	 */
+	if (nbytes > sizeof(tmpbuf)) {
+		tmplen = min_t(u32, nbytes, LRNG_DRNG_MAX_REQSIZE);
+		tmp_large = kmalloc(tmplen + LRNG_KCAPI_ALIGN, GFP_KERNEL);
+		if (!tmp_large)
+			tmplen = sizeof(tmpbuf);
+		else
+			tmp = PTR_ALIGN(tmp_large, LRNG_KCAPI_ALIGN);
+	}
+
+	while (nbytes) {
+		u32 todo = min_t(u32, nbytes, tmplen);
+		int rc = 0;
+
+		/* Reschedule if we received a large request. */
+		if ((tmp_large) && need_resched()) {
+			if (signal_pending(current)) {
+				if (ret == 0)
+					ret = -ERESTARTSYS;
+				break;
+			}
+			schedule();
+		}
+
+		rc = lrng_read_random(tmp, todo);
+		if (rc <= 0) {
+			if (rc < 0)
+				ret = rc;
+			break;
+		}
+		if (copy_to_user(buf, tmp, rc)) {
+			ret = -EFAULT;
+			break;
+		}
+
+		nbytes -= rc;
+		buf += rc;
+		ret += rc;
+	}
+
+	/* Wipe data just returned from memory */
+	if (tmp_large)
+		kzfree(tmp_large);
+	else
+		memzero_explicit(tmpbuf, sizeof(tmpbuf));
+
+	return ret;
+}
+
+static ssize_t
+lrng_read_common_block(int nonblock, char __user *buf, size_t nbytes,
+		       int (*lrng_read_random)(u8 *outbuf, u32 outbuflen))
+{
+	if (nbytes == 0)
+		return 0;
+
+	if (unlikely(!lrng_state_operational())) {
+		int ret;
+
+		if (nonblock)
+			return -EAGAIN;
+
+		ret = wait_event_interruptible(lrng_init_wait,
+					       lrng_state_operational());
+		if (unlikely(ret))
+			return ret;
+	}
+
+	while (1) {
+		ssize_t n = lrng_read_common(buf, nbytes, lrng_read_random);
+
+		if (n)
+			return n;
+
+		/* No entropy available. Maybe wait and retry. */
+		if (nonblock)
+			return -EAGAIN;
+
+		wait_event_interruptible(lrng_read_wait,
+					 lrng_have_entropy_full_trng());
+		if (signal_pending(current))
+			return -ERESTARTSYS;
+	}
+}
+
+static ssize_t lrng_read_block(struct file *file, char __user *buf,
+			       size_t nbytes, loff_t *ppos)
+{
+	return lrng_read_common_block(file->f_flags & O_NONBLOCK, buf, nbytes,
+				      lrng_sdrng_get_sleep);
+}
+
+static unsigned int lrng_trng_poll(struct file *file, poll_table *wait)
+{
+	__poll_t mask;
+
+	poll_wait(file, &lrng_read_wait, wait);
+	poll_wait(file, &lrng_write_wait, wait);
+	mask = 0;
+	if (lrng_have_entropy_full())
+		mask |= EPOLLIN | EPOLLRDNORM;
+	if (lrng_need_entropy())
+		mask |= EPOLLOUT | EPOLLWRNORM;
+	return mask;
+}
+
+static ssize_t lrng_drng_write_common(const char __user *buffer, size_t count,
+				      u32 entropy_bits)
+{
+	ssize_t ret = 0;
+	u8 buf[64] __aligned(LRNG_KCAPI_ALIGN);
+	const char __user *p = buffer;
+	u32 orig_entropy_bits = entropy_bits;
+
+	if (!lrng_get_available())
+		return -EAGAIN;
+
+	count = min_t(size_t, count, INT_MAX);
+	while (count > 0) {
+		size_t bytes = min_t(size_t, count, sizeof(buf));
+		u32 ent = min_t(u32, bytes<<3, entropy_bits);
+
+		if (copy_from_user(&buf, p, bytes))
+			return -EFAULT;
+		/* Inject data into entropy pool */
+		lrng_pool_lfsr(buf, bytes);
+		lrng_pool_add_entropy(ent);
+
+		count -= bytes;
+		p += bytes;
+		ret += bytes;
+		entropy_bits -= ent;
+
+		cond_resched();
+	}
+
+	/* Force reseed of secondary DRNG during next data request. */
+	if (!orig_entropy_bits)
+		lrng_sdrng_force_reseed();
+
+	return ret;
+}
+
+static ssize_t lrng_sdrng_read(struct file *file, char __user *buf,
+			       size_t nbytes, loff_t *ppos)
+{
+	if (!lrng_state_min_seeded())
+		pr_notice_ratelimited("%s - use of insufficiently seeded DRNG "
+				      "(%zu bytes read)\n", current->comm,
+				      nbytes);
+	else if (!lrng_state_operational())
+		pr_debug_ratelimited("%s - use of not fully seeded DRNG (%zu "
+				     "bytes read)\n", current->comm, nbytes);
+
+	return lrng_read_common(buf, nbytes, lrng_sdrng_get_sleep);
+}
+
+static ssize_t lrng_drng_write(struct file *file, const char __user *buffer,
+			       size_t count, loff_t *ppos)
+{
+	return lrng_drng_write_common(buffer, count, 0);
+}
+
+static long lrng_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
+{
+	int size, ent_count_bits;
+	int __user *p = (int __user *)arg;
+
+	switch (cmd) {
+	case RNDGETENTCNT:
+		ent_count_bits = lrng_avail_entropy();
+		if (put_user(ent_count_bits, p))
+			return -EFAULT;
+		return 0;
+	case RNDADDTOENTCNT:
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+		if (get_user(ent_count_bits, p))
+			return -EFAULT;
+		ent_count_bits = (int)lrng_avail_entropy() + ent_count_bits;
+		if (ent_count_bits < 0)
+			ent_count_bits = 0;
+		if (ent_count_bits > LRNG_POOL_SIZE_BITS)
+			ent_count_bits = LRNG_POOL_SIZE_BITS;
+		lrng_pool_set_entropy(ent_count_bits);
+		return 0;
+	case RNDADDENTROPY:
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+		if (get_user(ent_count_bits, p++))
+			return -EFAULT;
+		if (ent_count_bits < 0)
+			return -EINVAL;
+		if (get_user(size, p++))
+			return -EFAULT;
+		if (size < 0)
+			return -EINVAL;
+		/* there cannot be more entropy than data */
+		ent_count_bits = min(ent_count_bits, size<<3);
+		return lrng_drng_write_common((const char __user *)p, size,
+					      ent_count_bits);
+	case RNDZAPENTCNT:
+	case RNDCLEARPOOL:
+		/* Clear the entropy pool counter. */
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+		lrng_pool_set_entropy(0);
+		return 0;
+	case RNDRESEEDCRNG:
+		/*
+		 * We leave the capability check here since it is present
+		 * in the upstream's RNG implementation. Yet, user space
+		 * can trigger a reseed as easy as writing into /dev/random
+		 * or /dev/urandom where no privilege is needed.
+		 */
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+		/* Force a reseed of all secondary DRNGs */
+		lrng_sdrng_force_reseed();
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
+static int lrng_fasync(int fd, struct file *filp, int on)
+{
+	return fasync_helper(fd, filp, on, &fasync);
+}
+
+const struct file_operations random_fops = {
+	.read  = lrng_read_block,
+	.write = lrng_drng_write,
+	.poll  = lrng_trng_poll,
+	.unlocked_ioctl = lrng_ioctl,
+	.fasync = lrng_fasync,
+	.llseek = noop_llseek,
+};
+
+const struct file_operations urandom_fops = {
+	.read  = lrng_sdrng_read,
+	.write = lrng_drng_write,
+	.unlocked_ioctl = lrng_ioctl,
+	.fasync = lrng_fasync,
+	.llseek = noop_llseek,
+};
+
+/* These defines need to go to include/uapi/linux/random.h */
+#define GRND_INSECURE	0x0004
+#define GRND_TRUERANDOM	0x0008
+SYSCALL_DEFINE3(getrandom, char __user *, buf, size_t, count,
+		unsigned int, flags)
+{
+	if (flags & ~(GRND_NONBLOCK|GRND_RANDOM|GRND_INSECURE|GRND_TRUERANDOM))
+		return -EINVAL;
+
+	/*
+	 * Requesting insecure and blocking randomness at the same time makes
+	 * no sense.
+	 */
+	if ((flags &
+	     (GRND_INSECURE|GRND_RANDOM)) == (GRND_INSECURE|GRND_RANDOM))
+		return -EINVAL;
+
+	/* Only allow GRND_TRUERANDOM by itself or with NONBLOCK */
+	if ((flags & GRND_TRUERANDOM) &&
+	    ((flags &~ GRND_TRUERANDOM) != 0) &&
+	    ((flags &~ (GRND_TRUERANDOM | GRND_NONBLOCK)) != 0))
+		return -EINVAL;
+
+	if (count > INT_MAX)
+		count = INT_MAX;
+
+        if (flags & GRND_TRUERANDOM)
+		return lrng_read_common_block(flags & GRND_NONBLOCK, buf,
+					      count, lrng_trng_get);
+	if (flags & GRND_INSECURE)
+		return lrng_sdrng_read(NULL, buf, count, NULL);
+
+	return lrng_read_common_block(flags & GRND_NONBLOCK, buf, count,
+				      lrng_sdrng_get_sleep);
+
+}
diff --git a/drivers/char/lrng/lrng_internal.h b/drivers/char/lrng/lrng_internal.h
new file mode 100644
index 000000000000..675ba28bd2e6
--- /dev/null
+++ b/drivers/char/lrng/lrng_internal.h
@@ -0,0 +1,311 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
+/*
+ * Copyright (C) 2018 - 2019, Stephan Mueller <smueller@chronox.de>
+ */
+
+#ifndef _LRNG_INTERNAL_H
+#define _LRNG_INTERNAL_H
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+
+/*************************** General LRNG parameter ***************************/
+
+/* Security strength of LRNG -- this must match DRNG security strength */
+#define LRNG_DRNG_SECURITY_STRENGTH_BYTES 32
+#define LRNG_DRNG_SECURITY_STRENGTH_BITS (LRNG_DRNG_SECURITY_STRENGTH_BYTES * 8)
+#define LRNG_DRNG_BLOCKSIZE 64		/* Maximum of DRNG block sizes */
+
+/*
+ * SP800-90A defines a maximum request size of 1<<16 bytes. The given value is
+ * considered a safer margin. This applies to the secondary DRNGs.
+ *
+ * This value is allowed to be changed.
+ */
+#define LRNG_DRNG_MAX_REQSIZE		(1<<12)
+
+/*
+ * SP800-90A defines a maximum number of requests between reseeds of 2^48.
+ * The given value is considered a much safer margin, balancing requests for
+ * frequent reseeds with the need to conserve entropy. This value MUST NOT be
+ * larger than INT_MAX because it is used in an atomic_t. This applies to the
+ * secondary DRNGs.
+ *
+ * This value is allowed to be changed.
+ */
+#define LRNG_DRNG_RESEED_THRESH		(1<<20)
+
+/*
+ * Number of interrupts to be recorded to assume that DRNG security strength
+ * bits of entropy are received.
+ * Note: a value below the DRNG security strength should not be defined as this
+ *	 may imply the DRNG can never be fully seeded in case other noise
+ *	 sources are unavailable.
+ *
+ * This value is allowed to be changed.
+ */
+#define LRNG_IRQ_ENTROPY_BITS		LRNG_DRNG_SECURITY_STRENGTH_BITS
+
+/*
+ * Leave given amount of entropy in bits in entropy pool to serve
+ * GRND_TRUERANDOM called with CAP_SYS_ADMIN while /dev/urandom is stressed.
+ *
+ * This value is allowed to be changed.
+ */
+#define LRNG_EMERG_ENTROPY		(LRNG_DRNG_SECURITY_STRENGTH_BITS * 2)
+
+/*
+ * Leave given amount of entropy in bits in entropy to serve GRND_TRUERANDOM
+ * called without CAP_SYS_ADMIN. Providing TRNG data to unprivileged users
+ * should have the least priority and should not affect other users of entropy.
+ */
+#define LRNG_EMERG_ENTROPY_TRNG_UNPRIV	(LRNG_EMERG_ENTROPY * 2)
+
+/*
+ * Amount of entropy that is lost with the conditioning functions of LFSR and
+ * hash_df as shown with the entropy analysis compliant to SP800-90B.
+ */
+#define LRNG_CONDITIONING_ENTROPY_LOSS	1
+
+/*
+ * Min required seed entropy is 128 bits covering the minimum entropy
+ * requirement of SP800-131A and the German BSI's TR02102.
+ *
+ * This value is allowed to be changed.
+ */
+#define LRNG_FULL_SEED_ENTROPY_BITS	LRNG_DRNG_SECURITY_STRENGTH_BITS
+#define LRNG_MIN_SEED_ENTROPY_BITS	128
+#define LRNG_INIT_ENTROPY_BITS		32
+
+/*
+ * Oversampling factor of IRQ events to obtain
+ * LRNG_DRNG_SECURITY_STRENGTH_BYTES. This factor is used when a
+ * high-resolution time stamp is not available. In this case, jiffies and
+ * register contents are used to fill the entropy pool. These noise sources
+ * are much less entropic than the high-resolution timer. The entropy content
+ * is the entropy content assumed with LRNG_IRQ_ENTROPY_BITS divided by
+ * LRNG_IRQ_OVERSAMPLING_FACTOR.
+ *
+ * This value is allowed to be changed.
+ */
+#define LRNG_IRQ_OVERSAMPLING_FACTOR	10
+
+/*
+ * Alignmask which should cover all cipher implementations
+ * WARNING: If this is changed to a value larger than 8, manual
+ * alignment is necessary as older versions of GCC may not be capable
+ * of aligning stack variables at boundaries greater than 8.
+ * In this case, PTR_ALIGN must be used.
+ */
+#define LRNG_KCAPI_ALIGN		8
+
+/************************ Default DRNG implementation *************************/
+
+extern struct chacha20_state primary_chacha20;
+extern struct chacha20_state secondary_chacha20;
+extern const struct lrng_crypto_cb lrng_cc20_crypto_cb;
+void lrng_cc20_init_state(struct chacha20_state *state);
+
+/********************************** /proc *************************************/
+
+static inline void lrng_pool_inc_numa_node(void) { }
+
+/****************************** LRNG interfaces *******************************/
+
+extern u32 lrng_read_wakeup_bits;
+extern u32 lrng_write_wakeup_bits;
+extern int lrng_sdrng_reseed_max_time;
+
+void lrng_reader_wakeup(void);
+void lrng_writer_wakeup(void);
+void lrng_init_wakeup(void);
+void lrng_debug_report_seedlevel(const char *name);
+void lrng_process_ready_list(void);
+
+/************************** Entropy pool management ***************************/
+
+#define LRNG_POOL_SIZE			(128 << CONFIG_LRNG_POOL_SIZE)
+#define LRNG_POOL_WORD_BYTES		(sizeof(atomic_t))
+#define LRNG_POOL_SIZE_BYTES		(LRNG_POOL_SIZE * LRNG_POOL_WORD_BYTES)
+#define LRNG_POOL_SIZE_BITS		(LRNG_POOL_SIZE_BYTES * 8)
+#define LRNG_POOL_WORD_BITS		(LRNG_POOL_WORD_BYTES * 8)
+
+void lrng_state_init_seed_work(void);
+u32 lrng_avail_entropy(void);
+void lrng_set_entropy_thresh(u32 new);
+int lrng_pool_trylock(void);
+void lrng_pool_unlock(void);
+void lrng_reset_state(void);
+void lrng_pool_all_numa_nodes_seeded(void);
+bool lrng_state_min_seeded(void);
+bool lrng_state_fully_seeded(void);
+bool lrng_state_operational(void);
+bool lrng_pool_highres_timer(void);
+void lrng_pool_set_entropy(u32 entropy_bits);
+void lrng_pool_lfsr(const u8 *buf, u32 buflen);
+void lrng_pool_lfsr_nonaligned(const u8 *buf, u32 buflen);
+void lrng_pool_lfsr_u32(u32 value);
+void lrng_pool_add_irq(u32 irq_num);
+void lrng_pool_add_entropy(u32 entropy_bits);
+
+struct entropy_buf {
+	u8 a[LRNG_DRNG_SECURITY_STRENGTH_BYTES];
+	u8 b[LRNG_DRNG_SECURITY_STRENGTH_BYTES];
+	u8 c[LRNG_DRNG_SECURITY_STRENGTH_BYTES];
+	u32 now;
+};
+
+int lrng_fill_seed_buffer(const struct lrng_crypto_cb *crypto_cb, void *hash,
+			  struct entropy_buf *entropy_buf, u32 entropy_retain);
+void lrng_init_ops(u32 seed_bits);
+
+/************************** Jitter RNG Noise Source ***************************/
+
+#ifdef CONFIG_LRNG_JENT
+u32 lrng_get_jent(u8 *outbuf, unsigned int outbuflen);
+u32 lrng_jent_entropylevel(void);
+#else /* CONFIG_CRYPTO_JITTERENTROPY */
+static inline u32 lrng_get_jent(u8 *outbuf, unsigned int outbuflen) {return 0; }
+static inline u32 lrng_jent_entropylevel(void) { return 0; }
+#endif /* CONFIG_CRYPTO_JITTERENTROPY */
+
+/*************************** CPU-based Noise Source ***************************/
+
+u32 lrng_get_arch(u8 *outbuf);
+u32 lrng_slow_noise_req_entropy(u32 required_entropy_bits);
+
+/****************** True Random Number Generator processing *******************/
+
+#ifdef CONFIG_LRNG_TRNG_SUPPORT
+
+void lrng_trng_reset(void);
+void lrng_trng_init(void);
+int lrng_trng_get(u8 *outbuf, u32 outbuflen);
+int lrng_trng_seed(u8 *outbuf, u32 outbuflen, u32 entropy_retain);
+u32 lrng_trng_retain(void);
+# ifdef CONFIG_LRNG_DRNG_SWITCH
+int lrng_trng_switch(const struct lrng_crypto_cb *cb);
+# endif
+
+#else	/* CONFIG_LRNG_TRNG_SUPPORT */
+
+static inline void lrng_trng_reset(void) {}
+static inline void lrng_trng_init(void) {}
+static inline u32 lrng_trng_retain(void) { return 0; }
+
+static inline int lrng_trng_get(u8 *outbuf, u32 outbuflen)
+{
+	return -EOPNOTSUPP;
+}
+
+# ifdef CONFIG_LRNG_DRNG_SWITCH
+static inline int lrng_trng_switch(const struct lrng_crypto_cb *cb) {return 0; }
+# endif
+
+#endif	/* CONFIG_LRNG_TRNG_SUPPORT */
+
+/************************* secondary DRNG processing **************************/
+
+/* Secondary DRNG state handle */
+struct lrng_sdrng {
+	void *sdrng;				/* DRNG handle */
+	void *hash;				/* Hash handle */
+	const struct lrng_crypto_cb *crypto_cb;	/* Crypto callbacks */
+	atomic_t requests;			/* Number of DRNG requests */
+	unsigned long last_seeded;		/* Last time it was seeded */
+	bool fully_seeded;			/* Is DRNG fully seeded? */
+	bool force_reseed;			/* Force a reseed */
+	struct mutex lock;
+	spinlock_t spin_lock;
+};
+
+extern struct mutex lrng_crypto_cb_update;
+
+struct lrng_sdrng *lrng_sdrng_init_instance(void);
+struct lrng_sdrng *lrng_sdrng_atomic_instance(void);
+
+static __always_inline bool lrng_sdrng_is_atomic(struct lrng_sdrng *sdrng)
+{
+	return (sdrng->sdrng == lrng_sdrng_atomic_instance()->sdrng);
+}
+
+/* Lock the secondary DRNG */
+static __always_inline void lrng_sdrng_lock(struct lrng_sdrng *sdrng,
+					    unsigned long *flags)
+{
+	/* Use spin lock in case the atomic DRNG context is used */
+	if (lrng_sdrng_is_atomic(sdrng))
+		spin_lock_irqsave(&sdrng->spin_lock, *flags);
+	else
+		mutex_lock(&sdrng->lock);
+}
+
+/* Unlock the secondary DRNG */
+static __always_inline void lrng_sdrng_unlock(struct lrng_sdrng *sdrng,
+					      unsigned long *flags)
+{
+	if (lrng_sdrng_is_atomic(sdrng))
+		spin_unlock_irqrestore(&sdrng->spin_lock, *flags);
+	else
+		mutex_unlock(&sdrng->lock);
+}
+
+bool lrng_get_available(void);
+void lrng_set_available(void);
+void lrng_drngs_init_cc20(void);
+void lrng_sdrng_reset(struct lrng_sdrng *sdrng);
+int lrng_sdrng_get_atomic(u8 *outbuf, u32 outbuflen);
+int lrng_sdrng_get_sleep(u8 *outbuf, u32 outbuflen);
+void lrng_sdrng_force_reseed(void);
+void lrng_sdrng_seed_work(struct work_struct *dummy);
+
+static inline struct lrng_sdrng **lrng_sdrng_instances(void) { return NULL; }
+static inline void lrng_drngs_numa_alloc(void) { return; }
+
+/************************** Health Test linking code **************************/
+
+enum lrng_health_res {
+	lrng_health_pass,		/* Health test passes on time stamp */
+	lrng_health_fail_use,		/* Time stamp unhealthy, but mix in */
+	lrng_health_fail_drop		/* Time stamp unhealthy, drop it */
+};
+
+#ifdef CONFIG_LRNG_HEALTH_TESTS
+bool lrng_sp80090b_startup_complete(void);
+bool lrng_sp80090b_compliant(void);
+
+enum lrng_health_res lrng_health_test(u32 now_time);
+void lrng_health_disable(void);
+
+void lrng_reset(void);
+#else	/* CONFIG_LRNG_HEALTH_TESTS */
+static inline bool lrng_sp80090b_startup_complete(void) { return true; }
+static inline bool lrng_sp80090b_compliant(void) { return false; }
+
+static inline enum lrng_health_res
+lrng_health_test(u32 now_time) { return lrng_health_pass; }
+static inline void lrng_health_disable(void) { }
+#endif	/* CONFIG_LRNG_HEALTH_TESTS */
+
+/****************************** Helper code ***********************************/
+
+static inline u32 atomic_read_u32(atomic_t *v)
+{
+	return (u32)atomic_read(v);
+}
+
+/*************************** Auxiliary functions ******************************/
+
+void invalidate_batched_entropy(void);
+
+/***************************** Testing code ***********************************/
+
+#ifdef CONFIG_LRNG_TESTING
+bool lrng_raw_entropy_store(u32 value);
+#else	/* CONFIG_LRNG_TESTING */
+static inline bool lrng_raw_entropy_store(u32 value) { return false; }
+#endif	/* CONFIG_LRNG_TESTING */
+
+#endif /* _LRNG_INTERNAL_H */
diff --git a/drivers/char/lrng/lrng_pool.c b/drivers/char/lrng/lrng_pool.c
new file mode 100644
index 000000000000..6b46bf1a6b33
--- /dev/null
+++ b/drivers/char/lrng/lrng_pool.c
@@ -0,0 +1,671 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG Entropy pool management
+ *
+ * Copyright (C) 2016 - 2019, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <asm/irq_regs.h>
+#include <linux/lrng.h>
+#include <linux/percpu.h>
+#include <linux/random.h>
+#include <linux/utsname.h>
+#include <linux/workqueue.h>
+
+#include "lrng_internal.h"
+
+struct lrng_state {
+	bool lrng_operational;			/* Is DRNG operational? */
+	bool lrng_fully_seeded;			/* Is DRNG fully seeded? */
+	bool lrng_min_seeded;			/* Is DRNG minimally seeded? */
+	struct work_struct lrng_seed_work;	/* (re)seed work queue */
+};
+
+/* Status information about IRQ noise source */
+struct lrng_irq_info {
+	atomic_t num_events;	/* Number of healthy IRQs since last read */
+	atomic_t num_events_thresh;	/* Reseed threshold */
+	atomic_t reseed_in_progress;	/* Flag for on executing reseed */
+	bool irq_highres_timer;	/* Is high-resolution timer available? */
+	u32 irq_entropy_bits;	/* LRNG_IRQ_ENTROPY_BITS? */
+};
+
+/*
+ * This is the entropy pool used by the slow noise source. Its size should
+ * be at least as large as LRNG_DRNG_SECURITY_STRENGTH_BITS.
+ *
+ * The pool array is aligned to 8 bytes to comfort the kernel crypto API cipher
+ * implementations of the hash functions used to read the pool: for some
+ * accelerated implementations, we need an alignment to avoid a realignment
+ * which involves memcpy(). The alignment to 8 bytes should satisfy all crypto
+ * implementations.
+ *
+ * LRNG_POOL_SIZE is allowed to be changed only if the taps of the polynomial
+ * used for the LFSR are changed as well. The size must be in powers of 2 due
+ * to the mask handling in lrng_pool_lfsr_u32 which uses AND instead of modulo.
+ */
+struct lrng_pool {
+	union {
+		struct {
+			/*
+			 * hash_df implementation: counter, requested_bits and
+			 * pool form a linear buffer that is used in the
+			 * hash_df function specified in SP800-90A section
+			 * 10.3.1
+			 */
+			unsigned char counter;
+			__be32 requested_bits;
+
+			/* Pool */
+			atomic_t pool[LRNG_POOL_SIZE];
+			/* Ptr into pool for next IRQ word injection */
+			atomic_t pool_ptr;
+			/* rotate for LFSR */
+			atomic_t input_rotate;
+			/* All NUMA DRNGs seeded? */
+			bool all_online_numa_node_seeded;
+			/* IRQ noise source status info */
+			struct lrng_irq_info irq_info;
+			/* Serialize read of entropy pool */
+			spinlock_t lock;
+		};
+		/*
+		 * Static SHA-1 implementation in lrng_cc20_hash_buffer
+		 * processes data 64-byte-wise. Hence, ensure proper size
+		 * of LRNG entropy pool data structure.
+		 */
+		u8 hash_input_buf[LRNG_POOL_SIZE_BYTES + 64];
+	};
+};
+
+static struct lrng_pool lrng_pool __aligned(LRNG_KCAPI_ALIGN) = {
+	.irq_info	= {
+		.irq_entropy_bits	= LRNG_IRQ_ENTROPY_BITS,
+		.num_events_thresh	= ATOMIC_INIT(LRNG_INIT_ENTROPY_BITS +
+						LRNG_CONDITIONING_ENTROPY_LOSS),
+		/* Sample IRQ pointer data at least during boot */
+		.irq_highres_timer	= false },
+	.lock		= __SPIN_LOCK_UNLOCKED(lrng_pool.lock)
+};
+
+static struct lrng_state lrng_state = { false, false, false, };
+
+/********************************** Helper ***********************************/
+
+void lrng_state_init_seed_work(void)
+{
+	INIT_WORK(&lrng_state.lrng_seed_work, lrng_sdrng_seed_work);
+}
+
+static inline u32 lrng_entropy_to_data(u32 entropy_bits)
+{
+	return ((entropy_bits * lrng_pool.irq_info.irq_entropy_bits) /
+		LRNG_DRNG_SECURITY_STRENGTH_BITS);
+}
+
+static inline u32 lrng_data_to_entropy(u32 irqnum)
+{
+	return ((irqnum * LRNG_DRNG_SECURITY_STRENGTH_BITS) /
+		lrng_pool.irq_info.irq_entropy_bits);
+}
+
+u32 lrng_avail_entropy(void)
+{
+	return min_t(u32, LRNG_POOL_SIZE_BITS, lrng_data_to_entropy(
+			atomic_read_u32(&lrng_pool.irq_info.num_events)));
+}
+
+void lrng_set_entropy_thresh(u32 new)
+{
+	atomic_set(&lrng_pool.irq_info.num_events_thresh,
+		   lrng_entropy_to_data(new));
+}
+
+/*
+ * Reading of the LRNG pool is only allowed by one caller. The reading is
+ * only performed to (re)seed the TRNG or SDRNGs. Thus, if this "lock" is
+ * already taken, the reseeding operation is in progress. The caller is not
+ * intended to wait but continue with its other operation.
+ */
+int lrng_pool_trylock(void)
+{
+	return atomic_cmpxchg(&lrng_pool.irq_info.reseed_in_progress, 0, 1);
+}
+
+void lrng_pool_unlock(void)
+{
+	atomic_set(&lrng_pool.irq_info.reseed_in_progress, 0);
+}
+
+void lrng_reset_state(void)
+{
+	struct lrng_irq_info *irq_info = &lrng_pool.irq_info;
+
+	atomic_set(&irq_info->num_events, 0);
+	lrng_state.lrng_operational = false;
+	lrng_state.lrng_fully_seeded = false;
+	lrng_state.lrng_min_seeded = false;
+	pr_debug("reset LRNG\n");
+}
+
+void lrng_pool_all_numa_nodes_seeded(void)
+{
+	lrng_pool.all_online_numa_node_seeded = true;
+}
+
+bool lrng_state_min_seeded(void)
+{
+	return lrng_state.lrng_min_seeded;
+}
+
+bool lrng_state_fully_seeded(void)
+{
+	return lrng_state.lrng_fully_seeded;
+}
+
+bool lrng_state_operational(void)
+{
+	return lrng_state.lrng_operational;
+}
+
+bool lrng_pool_highres_timer(void)
+{
+	return lrng_pool.irq_info.irq_highres_timer;
+}
+
+void lrng_pool_set_entropy(u32 entropy_bits)
+{
+	atomic_set(&lrng_pool.irq_info.num_events,
+		   lrng_entropy_to_data(entropy_bits));
+}
+
+static void lrng_pool_configure(bool highres_timer, u32 irq_entropy_bits)
+{
+	struct lrng_irq_info *irq_info = &lrng_pool.irq_info;
+
+	irq_info->irq_highres_timer = highres_timer;
+	if (irq_info->irq_entropy_bits != irq_entropy_bits) {
+		irq_info->irq_entropy_bits = irq_entropy_bits;
+		/* Reset the threshold based on new oversampling factor. */
+		lrng_set_entropy_thresh(atomic_read_u32(
+						&irq_info->num_events_thresh));
+	}
+}
+
+static void __init lrng_init_time_source(void)
+{
+	if (random_get_entropy() || random_get_entropy()) {
+		/*
+		 * As the highres timer is identified here, previous interrupts
+		 * obtained during boot time are treated like a lowres-timer
+		 * would have been present.
+		 */
+		lrng_pool_configure(true, LRNG_IRQ_ENTROPY_BITS);
+	} else {
+		lrng_health_disable();
+		lrng_pool_configure(false, LRNG_IRQ_ENTROPY_BITS *
+					   LRNG_IRQ_OVERSAMPLING_FACTOR);
+		pr_warn("operating without high-resolution timer and applying "
+			"IRQ oversampling factor %u\n",
+			LRNG_IRQ_OVERSAMPLING_FACTOR);
+	}
+}
+
+core_initcall(lrng_init_time_source);
+
+/* invoke function with buffer aligned to 4 bytes */
+void lrng_pool_lfsr(const u8 *buf, u32 buflen)
+{
+	u32 *p_buf = (u32 *)buf;
+
+	for (; buflen >= 4; buflen -= 4)
+		lrng_pool_lfsr_u32(*p_buf++);
+
+	buf = (u8 *)p_buf;
+	while (buflen--)
+		lrng_pool_lfsr_u32(*buf++);
+}
+
+void lrng_pool_lfsr_nonaligned(const u8 *buf, u32 buflen)
+{
+	while (buflen) {
+		if (!((unsigned long)buf & (sizeof(u32) - 1))) {
+			lrng_pool_lfsr(buf, buflen);
+			return;
+		}
+
+		lrng_pool_lfsr_u32(*buf++);
+		buflen--;
+	}
+}
+
+/**************************** Interrupt processing ****************************/
+
+/*
+ * Implement a (modified) twisted Generalized Feedback Shift Register. (See M.
+ * Matsumoto & Y. Kurita, 1992.  Twisted GFSR generators. ACM Transactions on
+ * Modeling and Computer Simulation 2(3):179-194.  Also see M. Matsumoto & Y.
+ * Kurita, 1994.  Twisted GFSR generators II.  ACM Transactions on Modeling and
+ * Computer Simulation 4:254-266).
+ */
+static u32 const lrng_twist_table[8] = {
+	0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158,
+	0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 };
+
+/*
+ * The polynomials for the LFSR are taken from the document "Table of Linear
+ * Feedback Shift Registers" by Roy Ward, Tim Molteno, October 26, 2007.
+ * The first polynomial is from "Primitive Binary Polynomials" by Wayne
+ * Stahnke (1973) and is primitive as well as irreducible.
+ *
+ * Note, the tap values are smaller by one compared to the documentation because
+ * they are used as an index into an array where the index starts by zero.
+ *
+ * All polynomials were also checked to be primitive and irreducible with magma
+ * which ensures that the key property of the LFSR providing a compression
+ * function for entropy is guaranteed.
+ */
+static u32 const lrng_lfsr_polynomial[][4] = {
+	{ 127, 28, 26, 1 },			/* 128 words by Stahnke */
+	{ 255, 253, 250, 245 },			/* 256 words */
+	{ 511, 509, 506, 503 },			/* 512 words */
+	{ 1023, 1014, 1001, 1000 },		/* 1024 words */
+	{ 2047, 2034, 2033, 2028 },		/* 2048 words */
+	{ 4095, 4094, 4080, 4068 },		/* 4096 words */
+};
+
+/**
+ * Hot code path - inject data into entropy pool using LFSR
+ */
+void lrng_pool_lfsr_u32(u32 value)
+{
+	/*
+	 * Process the LFSR by altering not adjacent words but rather
+	 * more spaced apart words. Using a prime number ensures that all words
+	 * are processed evenly. As some the LFSR polynomials taps are close
+	 * together, processing adjacent words with the LSFR taps may be
+	 * inappropriate as the data just mixed-in at these taps may be not
+	 * independent from the current data to be mixed in.
+	 */
+	u32 ptr = (u32)atomic_add_return_relaxed(67, &lrng_pool.pool_ptr) &
+							(LRNG_POOL_SIZE - 1);
+	/*
+	 * Add 7 bits of rotation to the pool. At the beginning of the
+	 * pool, add an extra 7 bits rotation, so that successive passes
+	 * spread the input bits across the pool evenly.
+	 *
+	 * Note, there is a race between getting ptr and calculating
+	 * input_rotate when ptr is is obtained on two or more CPUs at the
+	 * same time. This race is irrelevant as it may only come into effect
+	 * if 3 or more CPUs race at the same time which is very unlikely. If
+	 * the race happens, it applies to one event only. As this rolling
+	 * supports the LFSR without being strictly needed, we accept this
+	 * race.
+	 */
+	u32 input_rotate = (u32)atomic_add_return_relaxed((ptr ? 7 : 14),
+					&lrng_pool.input_rotate) & 31;
+	u32 word = rol32(value, input_rotate);
+
+	BUILD_BUG_ON(LRNG_POOL_SIZE - 1 !=
+		     lrng_lfsr_polynomial[CONFIG_LRNG_POOL_SIZE][0]);
+	word ^= atomic_read_u32(&lrng_pool.pool[ptr]);
+	word ^= atomic_read_u32(&lrng_pool.pool[
+		(ptr + lrng_lfsr_polynomial[CONFIG_LRNG_POOL_SIZE][0]) &
+		       (LRNG_POOL_SIZE - 1)]);
+	word ^= atomic_read_u32(&lrng_pool.pool[
+		(ptr + lrng_lfsr_polynomial[CONFIG_LRNG_POOL_SIZE][1]) &
+		       (LRNG_POOL_SIZE - 1)]);
+	word ^= atomic_read_u32(&lrng_pool.pool[
+		(ptr + lrng_lfsr_polynomial[CONFIG_LRNG_POOL_SIZE][2]) &
+		       (LRNG_POOL_SIZE - 1)]);
+	word ^= atomic_read_u32(&lrng_pool.pool[
+		(ptr + lrng_lfsr_polynomial[CONFIG_LRNG_POOL_SIZE][3]) &
+		       (LRNG_POOL_SIZE - 1)]);
+
+	word = (word >> 3) ^ lrng_twist_table[word & 7];
+	atomic_set(&lrng_pool.pool[ptr], word);
+}
+
+/**
+ * Hot code path - mix data into entropy pool
+ */
+void lrng_pool_add_irq(u32 irq_num)
+{
+	struct lrng_irq_info *irq_info = &lrng_pool.irq_info;
+
+	atomic_add(irq_num, &irq_info->num_events);
+
+	/* Wake sleeping readers */
+	lrng_reader_wakeup();
+
+	/*
+	 * Once all secondary DRNGs are fully seeded, the interrupt noise
+	 * sources will not trigger any reseeding any more.
+	 */
+	if (likely(lrng_pool.all_online_numa_node_seeded))
+		return;
+
+	/* Only try to reseed if the DRNG is alive. */
+	if (!lrng_get_available())
+		return;
+
+	/* Only trigger the DRNG reseed if we have collected enough IRQs. */
+	if (atomic_read_u32(&lrng_pool.irq_info.num_events) <
+	    atomic_read_u32(&lrng_pool.irq_info.num_events_thresh))
+		return;
+
+	/* Ensure that the seeding only occurs once at any given time. */
+	if (lrng_pool_trylock())
+		return;
+
+	/* Seed the DRNG with IRQ noise. */
+	schedule_work(&lrng_state.lrng_seed_work);
+}
+
+void lrng_pool_add_entropy(u32 entropy_bits)
+{
+	lrng_pool_add_irq(lrng_entropy_to_data(entropy_bits));
+}
+
+/**
+ * Generate a hashed output of pool using the SP800-90A section 10.3.1 hash_df
+ * function
+ */
+static inline u32 lrng_pool_hash_df(const struct lrng_crypto_cb *crypto_cb,
+				    void *hash, u8 *outbuf, u32 requested_bits)
+{
+	struct lrng_pool *pool = &lrng_pool;
+	u32 digestsize, requested_bytes = requested_bits >> 3,
+	    generated_bytes = 0;
+	u8 digest[64] __aligned(LRNG_KCAPI_ALIGN);
+
+	digestsize = crypto_cb->lrng_hash_digestsize(hash);
+	if (digestsize > sizeof(digest)) {
+		pr_err("Digest buffer too small\n");
+		return 0;
+	}
+
+	pool->counter = 1;
+	pool->requested_bits = cpu_to_be32(requested_bytes << 3);
+
+	while (requested_bytes) {
+		u32 tocopy = min_t(u32, requested_bytes, digestsize);
+
+		/* The counter must not wrap */
+		if (pool->counter == 0)
+			goto out;
+
+		if (crypto_cb->lrng_hash_buffer(hash, (u8 *)pool,
+						LRNG_POOL_SIZE_BYTES + 64,
+						digest))
+			goto out;
+
+		/* Copy the data out to the caller */
+		memcpy(outbuf + generated_bytes, digest, tocopy);
+		requested_bytes -= tocopy;
+		generated_bytes += tocopy;
+		pool->counter++;
+	}
+
+out:
+	/* Mix read data back into pool for backtracking resistance */
+	if (generated_bytes)
+		lrng_pool_lfsr(outbuf, generated_bytes);
+	memzero_explicit(digest, digestsize);
+	return (generated_bytes<<3);
+}
+
+/**
+ * Read the entropy pool out for use.
+ *
+ * This function handles the translation from the number of received interrupts
+ * into an entropy statement. The conversion depends on LRNG_IRQ_ENTROPY_BITS
+ * which defines how many interrupts must be received to obtain 256 bits of
+ * entropy. With this value, the function lrng_data_to_entropy converts a given
+ * data size (received interrupts, requested amount of data, etc.) into an
+ * entropy statement. lrng_entropy_to_data does the reverse.
+ *
+ * Both functions are agnostic about the type of data: when the number of
+ * interrupts is processed by these functions, the resulting entropy value is in
+ * bits as we assume the entropy of interrupts is measured in bits. When data is
+ * processed, the entropy value is in bytes as the data is measured in bytes.
+ *
+ * @outbuf: buffer to store data in with size LRNG_DRNG_SECURITY_STRENGTH_BYTES
+ * @requested_entropy_bits: requested bits of entropy -- the function will
+ *			    return at least this amount of entropy if available
+ * @entropy_retain: amount of entropy in bits that should be left in the pool
+ * @return: estimated entropy from the IRQs that was obtained
+ */
+static u32 lrng_get_pool(const struct lrng_crypto_cb *crypto_cb, void *hash,
+			 u8 *outbuf, u32 requested_entropy_bits,
+			 u32 entropy_retain)
+{
+	struct lrng_pool *pool = &lrng_pool;
+	struct lrng_state *state = &lrng_state;
+	unsigned long flags;
+
+	u32 irq_num_events_used, irq_num_events, avail_entropy_bits;
+
+	/* This get_pool operation must only be called once at a given time! */
+	spin_lock_irqsave(&pool->lock, flags);
+
+	/* How many unused interrupts are in entropy pool? */
+	irq_num_events = atomic_read_u32(&lrng_pool.irq_info.num_events);
+	/* Convert available interrupts into entropy statement */
+	avail_entropy_bits = lrng_data_to_entropy(irq_num_events);
+
+	/* Cap available entropy to pool size */
+	avail_entropy_bits =
+			min_t(u32, avail_entropy_bits, LRNG_POOL_SIZE_BITS);
+
+	/* How much entropy we need to and can we use? */
+	if (unlikely(!state->lrng_fully_seeded)) {
+		/*
+		 * During boot time, we read 256 bits data with
+		 * avail_entropy_bits entropy. In case our conservative
+		 * entropy estimate underestimates the available entropy
+		 * we can transport as much available entropy as
+		 * possible. The TRNG does not operate as a TRNG yet.
+		 */
+		requested_entropy_bits =
+				LRNG_DRNG_SECURITY_STRENGTH_BITS;
+	} else {
+		/* Provide all entropy above retaining level */
+		if (avail_entropy_bits < entropy_retain) {
+			requested_entropy_bits = 0;
+			goto out;
+		}
+		avail_entropy_bits -= entropy_retain;
+		requested_entropy_bits = min_t(u32, avail_entropy_bits,
+					       requested_entropy_bits);
+	}
+
+	/* Hash is a compression function: we generate entropy amount of data */
+	requested_entropy_bits = round_down(requested_entropy_bits, 8);
+
+	requested_entropy_bits = lrng_pool_hash_df(crypto_cb, hash, outbuf,
+						   requested_entropy_bits);
+
+	/* Boot time: After getting the full buffer adjust the entropy value. */
+	requested_entropy_bits = min_t(u32, avail_entropy_bits,
+				       requested_entropy_bits);
+
+out:
+	/* Convert used entropy into interrupt number for subtraction */
+	irq_num_events_used = lrng_entropy_to_data(requested_entropy_bits);
+
+	/*
+	 * The hash_df operation entropy assessment shows that the output
+	 * entropy is one bit smaller than the input entropy. Therefore we
+	 * account for this one bit of entropy here: if we have sufficient
+	 * entropy in the LFSR, we say we used one bit of entropy more.
+	 * Otherwise we reduce the amount of entropy we say we generated with
+	 * the hash_df.
+	 */
+	if (irq_num_events_used) {
+		if ((irq_num_events_used + LRNG_CONDITIONING_ENTROPY_LOSS) <=
+		    lrng_entropy_to_data(avail_entropy_bits)) {
+			irq_num_events_used += LRNG_CONDITIONING_ENTROPY_LOSS;
+		} else {
+			if (unlikely(requested_entropy_bits <
+				     LRNG_CONDITIONING_ENTROPY_LOSS))
+				requested_entropy_bits = 0;
+			else
+				requested_entropy_bits -=
+						LRNG_CONDITIONING_ENTROPY_LOSS;
+		}
+	}
+
+	/*
+	 * New events might have arrived in the meanwhile and we don't
+	 * want to throw them away unconditionally. On the other hand,
+	 * these new events might have been mixed in before
+	 * lrng_hash_df_pool() had been able to draw any entropy
+	 * from the pool and thus, the pool capacity might have been
+	 * exceeded at some point. Note that in theory, some events
+	 * might get lost inbetween the atomic_read() and
+	 * atomic_set() below. But that's fine, because it's no real
+	 * concern while code preventing this would come at the cost of
+	 * additional complexity. Likewise, some events which arrived
+	 * after full or partial completion of the __lrng_hash_df_pool()
+	 * above might get unnecessarily thrown away by the min()
+	 * operation below; the same argument applies there.
+	 */
+	irq_num_events = atomic_read_u32(&lrng_pool.irq_info.num_events);
+	irq_num_events = min_t(u32, irq_num_events,
+			       lrng_entropy_to_data(LRNG_POOL_SIZE_BITS));
+	irq_num_events -= irq_num_events_used;
+	atomic_set(&lrng_pool.irq_info.num_events, irq_num_events);
+
+	spin_unlock_irqrestore(&pool->lock, flags);
+
+	/* Obtain entropy statement in bits from the used entropy */
+	pr_debug("obtained %u bits of entropy from %u newly collected "
+		 "interrupts - not using %u interrupts\n",
+		 requested_entropy_bits, irq_num_events_used,
+		 irq_num_events);
+
+	return requested_entropy_bits;
+}
+
+/* Fill the seed buffer with data from the noise sources */
+int lrng_fill_seed_buffer(const struct lrng_crypto_cb *crypto_cb, void *hash,
+			  struct entropy_buf *entropy_buf, u32 entropy_retain)
+{
+	struct lrng_state *state = &lrng_state;
+	u32 total_entropy_bits = 0;
+
+	/* Require at least 128 bits of entropy for any reseed. */
+	if (state->lrng_fully_seeded &&
+	    (lrng_avail_entropy() <
+	     lrng_slow_noise_req_entropy(lrng_read_wakeup_bits) +
+	      entropy_retain))
+		goto wakeup;
+
+	/*
+	 * Concatenate the output of the noise sources. This would be the
+	 * spot to add an entropy extractor logic if desired. Note, this
+	 * has the ability to collect entropy equal or larger than the DRNG
+	 * strength to be able to feed GRND_TRUERANDOM.
+	 */
+	total_entropy_bits = lrng_get_pool(crypto_cb, hash, entropy_buf->a,
+					   LRNG_DRNG_SECURITY_STRENGTH_BITS,
+					   entropy_retain);
+	total_entropy_bits += lrng_get_arch(entropy_buf->b);
+	total_entropy_bits += lrng_get_jent(entropy_buf->c,
+					    LRNG_DRNG_SECURITY_STRENGTH_BYTES);
+
+	/* also reseed the DRNG with the current time stamp */
+	entropy_buf->now = random_get_entropy();
+
+wakeup:
+	/*
+	 * Shall we wake up user space writers? This location covers
+	 * /dev/urandom as well, but also ensures that the user space provider
+	 * does not dominate the internal noise sources since in case the
+	 * first call of this function finds sufficient entropy in the TRNG, it
+	 * will not trigger the wakeup. This implies that when the next
+	 * /dev/urandom read happens, the TRNG is drained and the internal
+	 * noise sources are asked to feed the TRNG.
+	 */
+	lrng_writer_wakeup();
+
+	return total_entropy_bits;
+}
+
+/**
+ * Set the slow noise source reseed trigger threshold. The initial threshold
+ * is set to the minimum data size that can be read from the pool: a word. Upon
+ * reaching this value, the next seed threshold of 128 bits is set followed
+ * by 256 bits.
+ *
+ * @entropy_bits: size of entropy currently injected into DRNG
+ */
+void lrng_init_ops(u32 seed_bits)
+{
+	struct lrng_state *state = &lrng_state;
+
+	if (state->lrng_operational)
+		return;
+
+	/* DRNG is seeded with full security strength */
+	if (state->lrng_fully_seeded) {
+		state->lrng_operational = lrng_sp80090b_startup_complete();
+		lrng_init_wakeup();
+	} else if (seed_bits >= LRNG_FULL_SEED_ENTROPY_BITS) {
+		invalidate_batched_entropy();
+		state->lrng_fully_seeded = true;
+		state->lrng_operational = lrng_sp80090b_startup_complete();
+		state->lrng_min_seeded = true;
+		pr_info("LRNG fully seeded with %u bits of entropy\n",
+			seed_bits);
+		lrng_set_entropy_thresh(LRNG_FULL_SEED_ENTROPY_BITS +
+					LRNG_CONDITIONING_ENTROPY_LOSS);
+		lrng_process_ready_list();
+		lrng_init_wakeup();
+
+	} else if (!state->lrng_min_seeded) {
+
+		/* DRNG is seeded with at least 128 bits of entropy */
+		if (seed_bits >= LRNG_MIN_SEED_ENTROPY_BITS) {
+			invalidate_batched_entropy();
+			state->lrng_min_seeded = true;
+			pr_info("LRNG minimally seeded with %u bits of "
+				"entropy\n", seed_bits);
+			lrng_set_entropy_thresh(
+				lrng_slow_noise_req_entropy(
+					LRNG_FULL_SEED_ENTROPY_BITS +
+					LRNG_CONDITIONING_ENTROPY_LOSS));
+			lrng_process_ready_list();
+			lrng_init_wakeup();
+
+		/* DRNG is seeded with at least LRNG_INIT_ENTROPY_BITS bits */
+		} else if (seed_bits >= LRNG_INIT_ENTROPY_BITS) {
+			pr_info("LRNG initial entropy level %u bits of "
+				"entropy\n", seed_bits);
+			lrng_set_entropy_thresh(
+				lrng_slow_noise_req_entropy(
+					LRNG_MIN_SEED_ENTROPY_BITS +
+					LRNG_CONDITIONING_ENTROPY_LOSS));
+		}
+	}
+}
+
+int __init rand_initialize(void)
+{
+	ktime_t now_time = ktime_get_real();
+	unsigned int i, rand;
+
+	lrng_pool_lfsr_u32(now_time);
+	for (i = 0; i < LRNG_POOL_SIZE; i++) {
+		if (!arch_get_random_seed_int(&rand) &&
+		    !arch_get_random_int(&rand))
+			rand = random_get_entropy();
+		lrng_pool_lfsr_u32(rand);
+	}
+	lrng_pool_lfsr_nonaligned((u8 *)utsname(), sizeof(*(utsname())));
+
+	return 0;
+}
diff --git a/drivers/char/lrng/lrng_sdrng.c b/drivers/char/lrng/lrng_sdrng.c
new file mode 100644
index 000000000000..b01acfa05177
--- /dev/null
+++ b/drivers/char/lrng/lrng_sdrng.c
@@ -0,0 +1,420 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG secondary DRNG processing
+ *
+ * Copyright (C) 2016 - 2019, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/lrng.h>
+
+#include "lrng_internal.h"
+
+/*
+ * Maximum number of seconds between DRNG reseed intervals of the secondary
+ * DRNG. Note, this is enforced with the next request of random numbers from
+ * the secondary DRNG. Setting this value to zero implies a reseeding attempt
+ * before every generated random number.
+ */
+int lrng_sdrng_reseed_max_time = 600;
+
+static atomic_t lrng_avail = ATOMIC_INIT(0);
+
+DEFINE_MUTEX(lrng_crypto_cb_update);
+
+/* Secondary DRNG for /dev/urandom, getrandom(2), get_random_bytes */
+static struct lrng_sdrng lrng_sdrng_init = {
+	.sdrng		= &secondary_chacha20,
+	.crypto_cb	= &lrng_cc20_crypto_cb,
+	.lock		= __MUTEX_INITIALIZER(lrng_sdrng_init.lock),
+	.spin_lock	= __SPIN_LOCK_UNLOCKED(lrng_sdrng_init.spin_lock)
+};
+
+/*
+ * Secondary DRNG for get_random_bytes when called in atomic context. This
+ * DRNG will always use the ChaCha20 DRNG. It will never benefit from a
+ * DRNG switch like the "regular" secondary DRNG. If there was no DRNG
+ * switch, the atomic secondary DRNG is identical to the "regular" secondary
+ * DRNG.
+ *
+ * The reason for having this is due to the fact that DRNGs other than
+ * the ChaCha20 DRNG may sleep.
+ */
+static struct lrng_sdrng lrng_sdrng_atomic = {
+	.sdrng		= &secondary_chacha20,
+	.crypto_cb	= &lrng_cc20_crypto_cb,
+	.spin_lock	= __SPIN_LOCK_UNLOCKED(lrng_sdrng_atomic.spin_lock)
+};
+
+/********************************** Helper ************************************/
+
+bool lrng_get_available(void)
+{
+	return likely(atomic_read(&lrng_avail));
+}
+
+void lrng_set_available(void)
+{
+	atomic_set(&lrng_avail, 1);
+}
+
+struct lrng_sdrng *lrng_sdrng_init_instance(void)
+{
+	return &lrng_sdrng_init;
+}
+
+struct lrng_sdrng *lrng_sdrng_atomic_instance(void)
+{
+	return &lrng_sdrng_atomic;
+}
+
+void lrng_sdrng_reset(struct lrng_sdrng *sdrng)
+{
+	atomic_set(&sdrng->requests, LRNG_DRNG_RESEED_THRESH);
+	sdrng->last_seeded = jiffies;
+	sdrng->fully_seeded = false;
+	sdrng->force_reseed = true;
+	pr_debug("reset secondary DRNG\n");
+}
+
+/************************* Random Number Generation ***************************/
+
+/* Inject a data buffer into the secondary DRNG */
+static void lrng_sdrng_inject(struct lrng_sdrng *sdrng,
+			      const u8 *inbuf, u32 inbuflen)
+{
+	const char *drng_type = unlikely(sdrng == &lrng_sdrng_atomic) ?
+				"atomic" : "secondary";
+	unsigned long flags = 0;
+
+	BUILD_BUG_ON(LRNG_DRNG_RESEED_THRESH > INT_MAX);
+	pr_debug("seeding %s DRNG with %u bytes\n", drng_type, inbuflen);
+	lrng_sdrng_lock(sdrng, &flags);
+	if (sdrng->crypto_cb->lrng_drng_seed_helper(sdrng->sdrng,
+						    inbuf, inbuflen) < 0) {
+		pr_warn("seeding of %s DRNG failed\n", drng_type);
+		atomic_set(&sdrng->requests, 1);
+	} else {
+		pr_debug("%s DRNG stats since last seeding: %lu secs; "
+			 "generate calls: %d\n", drng_type,
+			 (time_after(jiffies, sdrng->last_seeded) ?
+			  (jiffies - sdrng->last_seeded) : 0) / HZ,
+			 (LRNG_DRNG_RESEED_THRESH -
+			  atomic_read(&sdrng->requests)));
+		sdrng->last_seeded = jiffies;
+		atomic_set(&sdrng->requests, LRNG_DRNG_RESEED_THRESH);
+		sdrng->force_reseed = false;
+
+		if (sdrng->sdrng == lrng_sdrng_atomic.sdrng) {
+			lrng_sdrng_atomic.last_seeded = jiffies;
+			atomic_set(&lrng_sdrng_atomic.requests,
+				   LRNG_DRNG_RESEED_THRESH);
+			lrng_sdrng_atomic.force_reseed = false;
+		}
+	}
+	lrng_sdrng_unlock(sdrng, &flags);
+}
+
+#ifdef CONFIG_LRNG_TRNG_SUPPORT
+static inline int _lrng_sdrng_seed(struct lrng_sdrng *sdrng)
+{
+	u8 seedbuf[LRNG_DRNG_SECURITY_STRENGTH_BYTES]
+						__aligned(LRNG_KCAPI_ALIGN);
+	int ret = lrng_trng_seed(seedbuf, sizeof(seedbuf),
+				 sdrng->fully_seeded ? LRNG_EMERG_ENTROPY : 0);
+
+	/* Update the DRNG state even though we received zero random data */
+	if (ret < 0) {
+		/* Try to reseed at next round */
+		atomic_set(&sdrng->requests, 1);
+		return ret;
+	}
+
+	lrng_sdrng_inject(sdrng, seedbuf, sizeof(seedbuf));
+	memzero_explicit(seedbuf, sizeof(seedbuf));
+
+	return ret;
+}
+#else	/* CONFIG_LRNG_TRNG_SUPPORT */
+static inline int _lrng_sdrng_seed(struct lrng_sdrng *sdrng)
+{
+	struct entropy_buf seedbuf __aligned(LRNG_KCAPI_ALIGN);
+	unsigned long flags = 0;
+	u32 total_entropy_bits;
+	int ret;
+
+	lrng_sdrng_lock(sdrng, &flags);
+	total_entropy_bits = lrng_fill_seed_buffer(sdrng->crypto_cb,
+						   sdrng->hash, &seedbuf, 0);
+	lrng_sdrng_unlock(sdrng, &flags);
+
+	/* Allow the seeding operation to be called again */
+	lrng_pool_unlock();
+	lrng_init_ops(total_entropy_bits);
+	ret = total_entropy_bits >> 3;
+
+	lrng_sdrng_inject(sdrng, (u8 *)&seedbuf, sizeof(seedbuf));
+	memzero_explicit(&seedbuf, sizeof(seedbuf));
+
+	return ret;
+}
+#endif	/* CONFIG_LRNG_TRNG_SUPPORT */
+
+static int lrng_sdrng_get(struct lrng_sdrng *sdrng, u8 *outbuf, u32 outbuflen);
+static void lrng_sdrng_seed(struct lrng_sdrng *sdrng)
+{
+	int ret = _lrng_sdrng_seed(sdrng);
+
+	if (ret >= LRNG_DRNG_SECURITY_STRENGTH_BYTES)
+		sdrng->fully_seeded = true;
+
+	BUILD_BUG_ON(LRNG_MIN_SEED_ENTROPY_BITS >
+		     LRNG_DRNG_SECURITY_STRENGTH_BITS);
+
+	/*
+	 * Reseed atomic DRNG from current secondary DRNG,
+	 *
+	 * We can obtain random numbers from secondary DRNG as the lock type
+	 * chosen by lrng_sdrng_get is usable with the current caller.
+	 */
+	if ((sdrng->sdrng != lrng_sdrng_atomic.sdrng) &&
+	    (lrng_sdrng_atomic.force_reseed ||
+	     atomic_read(&lrng_sdrng_atomic.requests) <= 0 ||
+	     time_after(jiffies, lrng_sdrng_atomic.last_seeded +
+			lrng_sdrng_reseed_max_time * HZ))) {
+		u8 seedbuf[LRNG_DRNG_SECURITY_STRENGTH_BYTES]
+						__aligned(LRNG_KCAPI_ALIGN);
+
+		ret = lrng_sdrng_get(sdrng, seedbuf, sizeof(seedbuf));
+
+		if (ret < 0) {
+			pr_warn("Error generating random numbers for atomic "
+				"DRNG: %d\n", ret);
+		} else {
+			lrng_sdrng_inject(&lrng_sdrng_atomic, seedbuf, ret);
+		}
+		memzero_explicit(&seedbuf, sizeof(seedbuf));
+	}
+}
+
+static inline void _lrng_sdrng_seed_work(struct lrng_sdrng *sdrng, u32 node)
+{
+	pr_debug("reseed triggered by interrupt noise source "
+		 "for secondary DRNG on NUMA node %d\n", node);
+	lrng_sdrng_seed(sdrng);
+	if (sdrng->fully_seeded) {
+		/* Prevent reseed storm */
+		sdrng->last_seeded += node * 100 * HZ;
+		/* Prevent draining of pool on idle systems */
+		lrng_sdrng_reseed_max_time += 100;
+	}
+}
+
+/**
+ * DRNG reseed trigger: Kernel thread handler triggered by the schedule_work()
+ */
+void lrng_sdrng_seed_work(struct work_struct *dummy)
+{
+	struct lrng_sdrng **lrng_sdrng = lrng_sdrng_instances();
+	u32 node;
+
+	if (lrng_sdrng) {
+		for_each_online_node(node) {
+			struct lrng_sdrng *sdrng = lrng_sdrng[node];
+
+			if (sdrng && !sdrng->fully_seeded) {
+				_lrng_sdrng_seed_work(sdrng, node);
+				goto out;
+			}
+		}
+		lrng_pool_all_numa_nodes_seeded();
+	} else {
+		if (!lrng_sdrng_init.fully_seeded)
+			_lrng_sdrng_seed_work(&lrng_sdrng_init, 0);
+	}
+
+out:
+	/* Allow the seeding operation to be called again */
+	lrng_pool_unlock();
+}
+
+/* Force all secondary DRNGs to reseed before next generation */
+void lrng_sdrng_force_reseed(void)
+{
+	struct lrng_sdrng **lrng_sdrng = lrng_sdrng_instances();
+	u32 node;
+
+	if (!lrng_sdrng) {
+		lrng_sdrng_init.force_reseed = true;
+		pr_debug("force reseed of initial secondary DRNG\n");
+		return;
+	}
+	for_each_online_node(node) {
+		struct lrng_sdrng *sdrng = lrng_sdrng[node];
+
+		if (!sdrng)
+			continue;
+
+		sdrng->force_reseed = true;
+		pr_debug("force reseed of secondary DRNG on node %u\n", node);
+	}
+	lrng_sdrng_atomic.force_reseed = true;
+}
+
+/**
+ * Get random data out of the secondary DRNG which is reseeded frequently.
+ *
+ * @outbuf: buffer for storing random data
+ * @outbuflen: length of outbuf
+ * @return: < 0 in error case (DRNG generation or update failed)
+ *	    >=0 returning the returned number of bytes
+ */
+static int lrng_sdrng_get(struct lrng_sdrng *sdrng, u8 *outbuf, u32 outbuflen)
+{
+	unsigned long flags = 0;
+	u32 processed = 0;
+
+	if (!outbuf || !outbuflen)
+		return 0;
+
+	outbuflen = min_t(size_t, outbuflen, INT_MAX);
+
+	lrng_drngs_init_cc20();
+
+	while (outbuflen) {
+		u32 todo = min_t(u32, outbuflen, LRNG_DRNG_MAX_REQSIZE);
+		int ret;
+
+		/* All but the atomic DRNG are seeded during generation */
+		if (atomic_dec_and_test(&sdrng->requests) ||
+		    sdrng->force_reseed ||
+		    time_after(jiffies, sdrng->last_seeded +
+			       lrng_sdrng_reseed_max_time * HZ)) {
+			if (likely(sdrng != &lrng_sdrng_atomic)) {
+				if (lrng_pool_trylock())
+					atomic_set(&sdrng->requests, 1);
+				else
+					lrng_sdrng_seed(sdrng);
+			}
+		}
+
+		lrng_sdrng_lock(sdrng, &flags);
+		ret = sdrng->crypto_cb->lrng_drng_generate_helper(
+					sdrng->sdrng, outbuf + processed, todo);
+		lrng_sdrng_unlock(sdrng, &flags);
+		if (ret <= 0) {
+			pr_warn("getting random data from secondary DRNG "
+				"failed (%d)\n", ret);
+			return -EFAULT;
+		}
+		processed += ret;
+		outbuflen -= ret;
+	}
+
+	return processed;
+}
+
+int lrng_sdrng_get_atomic(u8 *outbuf, u32 outbuflen)
+{
+	return lrng_sdrng_get(&lrng_sdrng_atomic, outbuf, outbuflen);
+}
+
+int lrng_sdrng_get_sleep(u8 *outbuf, u32 outbuflen)
+{
+	struct lrng_sdrng **lrng_sdrng = lrng_sdrng_instances();
+	struct lrng_sdrng *sdrng = &lrng_sdrng_init;
+	int node = numa_node_id();
+
+	might_sleep();
+
+	if (lrng_sdrng && lrng_sdrng[node] && lrng_sdrng[node]->fully_seeded)
+		sdrng = lrng_sdrng[node];
+
+	return lrng_sdrng_get(sdrng, outbuf, outbuflen);
+}
+
+/* Initialize the default DRNG during boot */
+void lrng_drngs_init_cc20(void)
+{
+	unsigned long flags = 0;
+
+	if (lrng_get_available())
+		return;
+
+	lrng_sdrng_lock(&lrng_sdrng_init, &flags);
+	if (lrng_get_available()) {
+		lrng_sdrng_unlock(&lrng_sdrng_init, &flags);
+		return;
+	}
+
+	lrng_sdrng_reset(&lrng_sdrng_init);
+	lrng_cc20_init_state(&secondary_chacha20);
+	lrng_state_init_seed_work();
+	lrng_sdrng_unlock(&lrng_sdrng_init, &flags);
+
+	lrng_sdrng_lock(&lrng_sdrng_atomic, &flags);
+	lrng_sdrng_reset(&lrng_sdrng_atomic);
+	/*
+	 * We do not initialize the state of the atomic DRNG as it is identical
+	 * to the secondary DRNG at this point.
+	 */
+	lrng_sdrng_unlock(&lrng_sdrng_atomic, &flags);
+
+	lrng_trng_init();
+
+	lrng_set_available();
+}
+
+/* Reset LRNG such that all existing entropy is gone */
+static void _lrng_reset(struct work_struct *work)
+{
+	struct lrng_sdrng **lrng_sdrng = lrng_sdrng_instances();
+	unsigned long flags = 0;
+
+	lrng_reset_state();
+	lrng_trng_reset();
+
+	if (!lrng_sdrng) {
+		lrng_sdrng_lock(&lrng_sdrng_init, &flags);
+		lrng_sdrng_reset(&lrng_sdrng_init);
+		lrng_sdrng_unlock(&lrng_sdrng_init, &flags);
+	} else {
+		u32 node;
+
+		for_each_online_node(node) {
+			struct lrng_sdrng *sdrng = lrng_sdrng[node];
+
+			if (!sdrng)
+				continue;
+			lrng_sdrng_lock(sdrng, &flags);
+			lrng_sdrng_reset(sdrng);
+			lrng_sdrng_unlock(sdrng, &flags);
+		}
+	}
+	lrng_set_entropy_thresh(LRNG_INIT_ENTROPY_BITS +
+				LRNG_CONDITIONING_ENTROPY_LOSS);
+}
+
+static DECLARE_WORK(lrng_reset_work, _lrng_reset);
+
+void lrng_reset(void)
+{
+	schedule_work(&lrng_reset_work);
+}
+
+/***************************** Initialize LRNG *******************************/
+
+static int __init lrng_init(void)
+{
+	lrng_drngs_init_cc20();
+
+	lrng_drngs_numa_alloc();
+	return 0;
+}
+
+late_initcall(lrng_init);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
+MODULE_DESCRIPTION("Linux Random Number Generator");
diff --git a/drivers/char/lrng/lrng_sw_noise.c b/drivers/char/lrng/lrng_sw_noise.c
new file mode 100644
index 000000000000..36b6382ffe6d
--- /dev/null
+++ b/drivers/char/lrng/lrng_sw_noise.c
@@ -0,0 +1,144 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG Slow Noise Source: Interrupt data collection
+ *
+ * Copyright (C) 2016 - 2019, Stephan Mueller <smueller@chronox.de>
+ */
+
+#include <asm/irq_regs.h>
+#include <asm/ptrace.h>
+#include <linux/random.h>
+
+#include "lrng_internal.h"
+
+/*
+ * To limit the impact on the interrupt handling, the LRNG concatenates
+ * entropic LSB parts of the time stamps in a per-CPU array and only
+ * injects them into the entropy pool when the array is full.
+ */
+/* Number of time values to store in the array */
+#define LRNG_TIME_NUM_VALUES		(64)
+/* Mask of LSB of time stamp to store */
+#define LRNG_TIME_WORD_MASK		(LRNG_TIME_NUM_VALUES - 1)
+
+/* Store multiple integers in one u32 */
+#define LRNG_TIME_SLOTSIZE_BITS		(8)
+#define LRNG_TIME_SLOTSIZE_MASK		((1 << LRNG_TIME_SLOTSIZE_BITS) - 1)
+#define LRNG_TIME_ARRAY_MEMBER_BITS	(sizeof(u32) << 3)
+#define LRNG_TIME_SLOTS_PER_UINT	(LRNG_TIME_ARRAY_MEMBER_BITS / \
+					 LRNG_TIME_SLOTSIZE_BITS)
+#define LRNG_TIME_SLOTS_MASK		(LRNG_TIME_SLOTS_PER_UINT - 1)
+#define LRNG_TIME_ARRAY_SIZE		(LRNG_TIME_NUM_VALUES /	\
+					 LRNG_TIME_SLOTS_PER_UINT)
+
+/* Holder of time stamps before mixing them into the entropy pool */
+static DEFINE_PER_CPU(u32 [LRNG_TIME_ARRAY_SIZE], lrng_time);
+static DEFINE_PER_CPU(u32, lrng_time_ptr) = 0;
+static DEFINE_PER_CPU(u8, lrng_time_irqs) = 0;
+
+/* Starting bit index of slot */
+static inline unsigned int lrng_time_slot2bitindex(unsigned int slot)
+{
+	return (LRNG_TIME_SLOTSIZE_BITS * slot);
+}
+
+/* Convert index into the array index */
+static inline unsigned int lrng_time_idx2array(unsigned int idx)
+{
+	return idx / LRNG_TIME_SLOTS_PER_UINT;
+}
+
+/* Convert index into the slot of a given array index */
+static inline unsigned int lrng_time_idx2slot(unsigned int idx)
+{
+	return idx & LRNG_TIME_SLOTS_MASK;
+}
+
+/* Convert value into slot value */
+static inline unsigned int lrng_time_slot_val(unsigned int val,
+					      unsigned int slot)
+{
+	return val << lrng_time_slot2bitindex(slot);
+}
+
+/**
+ * Batching up of entropy in per-CPU array before injecting into entropy pool.
+ */
+static inline void lrng_time_process(void)
+{
+	u32 i, ptr, now_time = random_get_entropy() &
+			       (likely(lrng_state_fully_seeded()) ?
+				LRNG_TIME_SLOTSIZE_MASK : (u32)-1);
+	enum lrng_health_res health_test;
+
+	/* Ensure sufficient space in lrng_time_irqs */
+	BUILD_BUG_ON(LRNG_TIME_NUM_VALUES >= (1 << (sizeof(u8) << 3)));
+	BUILD_BUG_ON(LRNG_TIME_ARRAY_MEMBER_BITS % LRNG_TIME_SLOTSIZE_BITS);
+
+	if (lrng_raw_entropy_store(now_time))
+		return;
+
+	health_test = lrng_health_test(now_time);
+	if (health_test > lrng_health_fail_use)
+		return;
+
+	/* During boot time, we mix the full time stamp directly into LFSR */
+	if (unlikely(!lrng_state_fully_seeded())) {
+		lrng_pool_lfsr_u32(now_time);
+		if (health_test == lrng_health_pass)
+			lrng_pool_add_irq(1);
+		return;
+	}
+
+	ptr = this_cpu_inc_return(lrng_time_ptr) & LRNG_TIME_WORD_MASK;
+	this_cpu_or(lrng_time[lrng_time_idx2array(ptr)],
+		    lrng_time_slot_val(now_time & LRNG_TIME_SLOTSIZE_MASK,
+				       lrng_time_idx2slot(ptr)));
+
+	/* Interrupt delivers entropy if health test passes */
+	if (health_test == lrng_health_pass)
+		this_cpu_inc(lrng_time_irqs);
+
+	/* Only mix the buffer of time stamps into LFSR when wrapping */
+	if (ptr < LRNG_TIME_WORD_MASK)
+		return;
+
+	for (i = 0; i < LRNG_TIME_ARRAY_SIZE; i++) {
+		lrng_pool_lfsr_u32(this_cpu_read(lrng_time[i]));
+		this_cpu_write(lrng_time[i], 0);
+	}
+	lrng_pool_add_irq(this_cpu_read(lrng_time_irqs));
+	this_cpu_write(lrng_time_irqs, 0);
+}
+
+/**
+ * Hot code path - Callback for interrupt handler
+ */
+void add_interrupt_randomness(int irq, int irq_flags)
+{
+	lrng_time_process();
+
+	if (!lrng_pool_highres_timer()) {
+		struct pt_regs *regs = get_irq_regs();
+		static atomic_t reg_idx = ATOMIC_INIT(0);
+		u64 ip;
+
+		lrng_pool_lfsr_u32(jiffies);
+		lrng_pool_lfsr_u32(irq);
+		lrng_pool_lfsr_u32(irq_flags);
+
+		if (regs) {
+			u32 *ptr = (u32 *)regs;
+			int reg_ptr = atomic_add_return_relaxed(1, &reg_idx);
+			size_t n = (sizeof(struct pt_regs) / sizeof(u32));
+
+			ip = instruction_pointer(regs);
+			lrng_pool_lfsr_u32(*(ptr + (reg_ptr % n)));
+		} else
+			ip = _RET_IP_;
+
+		lrng_pool_lfsr_u32(ip >> 32);
+		lrng_pool_lfsr_u32(ip);
+	}
+}
+EXPORT_SYMBOL(add_interrupt_randomness);
diff --git a/include/linux/lrng.h b/include/linux/lrng.h
new file mode 100644
index 000000000000..794c061d3514
--- /dev/null
+++ b/include/linux/lrng.h
@@ -0,0 +1,71 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
+/*
+ * Copyright (C) 2018 - 2019, Stephan Mueller <smueller@chronox.de>
+ */
+
+#ifndef _LRNG_H
+#define _LRNG_H
+
+#include <linux/errno.h>
+#include <linux/types.h>
+
+/**
+ * struct lrng_crypto_cb - cryptographic callback functions
+ * @lrng_drng_name		Name of DRNG
+ * @lrng_hash_name		Name of Hash used for reading entropy pool
+ * @lrng_drng_alloc:		Allocate DRNG -- the provided integer should be
+ *				used for sanity checks.
+ *				return: allocated data structure or PTR_ERR on
+ *					error
+ * @lrng_drng_dealloc:		Deallocate DRNG
+ * @lrng_drng_seed_helper:	Seed the DRNG with data of arbitrary length
+ *				drng: is pointer to data structure allocated
+ *				      with lrng_drng_alloc
+ *				return: >= 0 on success, < 0 on error
+ * @lrng_drng_generate_helper:	Generate random numbers from the DRNG with
+ *				arbitrary length
+ * @lrng_drng_generate_helper_full: Generate random numbers from the DRNG with
+ *				    arbitrary length where the output is
+ *				    capable of providing 1 bit of entropy per
+ *				    data bit.
+ *				    return: generated number of bytes,
+ *					    < 0 on error
+ * @lrng_hash_alloc:		Allocate the hash for reading the entropy pool
+ *				return: allocated data structure (NULL is
+ *					success too) or ERR_PTR on error
+ * @lrng_hash_dealloc:		Deallocate Hash
+ * @lrng_hash_digestsize:	Return the digestsize for the used hash to read
+ *				out entropy pool
+ *				hash: is pointer to data structure allocated
+ *				      with lrng_hash_alloc
+ *				return: size of digest of hash in bytes
+ * @lrng_hash_buffer:		Generate hash
+ *				hash: is pointer to data structure allocated
+ *				      with lrng_hash_alloc
+ *				return: 0 on success, < 0 on error
+ */
+struct lrng_crypto_cb {
+	const char *(*lrng_drng_name)(void);
+	const char *(*lrng_hash_name)(void);
+	void *(*lrng_drng_alloc)(u32 sec_strength);
+	void (*lrng_drng_dealloc)(void *drng);
+	int (*lrng_drng_seed_helper)(void *drng, const u8 *inbuf, u32 inbuflen);
+	int (*lrng_drng_generate_helper)(void *drng, u8 *outbuf, u32 outbuflen);
+	int (*lrng_drng_generate_helper_full)(void *drng, u8 *outbuf,
+					      u32 outbuflen);
+	void *(*lrng_hash_alloc)(const u8 *key, u32 keylen);
+	void (*lrng_hash_dealloc)(void *hash);
+	u32 (*lrng_hash_digestsize)(void *hash);
+	int (*lrng_hash_buffer)(void *hash, const u8 *inbuf, u32 inbuflen,
+				u8 *digest);
+};
+
+/* Register cryptographic backend */
+#ifdef CONFIG_LRNG_DRNG_SWITCH
+int lrng_set_drng_cb(const struct lrng_crypto_cb *cb);
+#else	/* CONFIG_LRNG_DRNG_SWITCH */
+static inline int
+lrng_set_drng_cb(const struct lrng_crypto_cb *cb) { return -EOPNOTSUPP; }
+#endif	/* CONFIG_LRNG_DRNG_SWITCH */
+
+#endif /* _LRNG_H */
-- 
2.23.0





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v26 02/12] LRNG - allocate one SDRNG instance per NUMA node
  2019-11-23 20:08   ` [PATCH v26 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
  2019-11-23 20:10     ` [PATCH v26 01/12] Linux Random Number Generator Stephan Müller
@ 2019-11-23 20:10     ` Stephan Müller
  2019-11-23 20:11     ` [PATCH v26 03/12] LRNG - sysctls and /proc interface Stephan Müller
                       ` (10 subsequent siblings)
  12 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-23 20:10 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap

In order to improve NUMA-locality when serving getrandom(2) requests,
allocate one DRNG instance per node.

The SDRNG instance that is present right from the start of the kernel is
reused as the first per-NUMA-node SDRNG. For all remaining online NUMA
nodes a new SDRNG instance is allocated.

During boot time, the multiple SDRNG instances are seeded sequentially.
With this, the first SDRNG instance (referenced as the initial SDRNG
in the code) is completely seeded with 256 bits of entropy before the
next SDRNG instance is completely seeded.

When random numbers are requested, the NUMA-node-local SDRNG is checked
whether it has been already fully seeded. If this is not the case, the
initial SDRNG is used to serve the request.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Makefile        |   2 +
 drivers/char/lrng/lrng_internal.h |   5 ++
 drivers/char/lrng/lrng_numa.c     | 101 ++++++++++++++++++++++++++++++
 3 files changed, 108 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_numa.c

diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index 2761623715d2..a00cddb45773 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -7,3 +7,5 @@ obj-y				+= lrng_pool.o lrng_aux.o \
 				   lrng_sw_noise.o lrng_archrandom.o \
 				   lrng_sdrng.o lrng_chacha20.o \
 				   lrng_interfaces.o \
+
+obj-$(CONFIG_NUMA)		+= lrng_numa.o
diff --git a/drivers/char/lrng/lrng_internal.h b/drivers/char/lrng/lrng_internal.h
index 675ba28bd2e6..fb7890939089 100644
--- a/drivers/char/lrng/lrng_internal.h
+++ b/drivers/char/lrng/lrng_internal.h
@@ -261,8 +261,13 @@ int lrng_sdrng_get_sleep(u8 *outbuf, u32 outbuflen);
 void lrng_sdrng_force_reseed(void);
 void lrng_sdrng_seed_work(struct work_struct *dummy);
 
+#ifdef CONFIG_NUMA
+struct lrng_sdrng **lrng_sdrng_instances(void);
+void lrng_drngs_numa_alloc(void);
+#else	/* CONFIG_NUMA */
 static inline struct lrng_sdrng **lrng_sdrng_instances(void) { return NULL; }
 static inline void lrng_drngs_numa_alloc(void) { return; }
+#endif /* CONFIG_NUMA */
 
 /************************** Health Test linking code **************************/
 
diff --git a/drivers/char/lrng/lrng_numa.c b/drivers/char/lrng/lrng_numa.c
new file mode 100644
index 000000000000..5401f927919a
--- /dev/null
+++ b/drivers/char/lrng/lrng_numa.c
@@ -0,0 +1,101 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG NUMA support
+ *
+ * Copyright (C) 2016 - 2019, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/lrng.h>
+#include <linux/slab.h>
+
+#include "lrng_internal.h"
+
+static struct lrng_sdrng **lrng_sdrng __read_mostly = NULL;
+
+struct lrng_sdrng **lrng_sdrng_instances(void)
+{
+	return lrng_sdrng;
+}
+
+/* Allocate the data structures for the per-NUMA node DRNGs */
+static void _lrng_drngs_numa_alloc(struct work_struct *work)
+{
+	struct lrng_sdrng **sdrngs;
+	struct lrng_sdrng *lrng_sdrng_init = lrng_sdrng_init_instance();
+	u32 node;
+	bool init_sdrng_used = false;
+
+	mutex_lock(&lrng_crypto_cb_update);
+
+	/* per-NUMA-node DRNGs are already present */
+	if (lrng_sdrng)
+		goto unlock;
+
+	sdrngs = kcalloc(nr_node_ids, sizeof(void *), GFP_KERNEL|__GFP_NOFAIL);
+	for_each_online_node(node) {
+		struct lrng_sdrng *sdrng;
+
+		if (!init_sdrng_used) {
+			sdrngs[node] = lrng_sdrng_init;
+			init_sdrng_used = true;
+			continue;
+		}
+
+		sdrng = kmalloc_node(sizeof(struct lrng_sdrng),
+				     GFP_KERNEL|__GFP_NOFAIL, node);
+		memset(sdrng, 0, sizeof(lrng_sdrng));
+
+		sdrng->crypto_cb = lrng_sdrng_init->crypto_cb;
+		sdrng->sdrng = sdrng->crypto_cb->lrng_drng_alloc(
+					LRNG_DRNG_SECURITY_STRENGTH_BYTES);
+		if (IS_ERR(sdrng->sdrng)) {
+			kfree(sdrng);
+			goto err;
+		}
+
+		mutex_init(&sdrng->lock);
+		spin_lock_init(&sdrng->spin_lock);
+
+		/*
+		 * No reseeding of NUMA DRNGs from previous DRNGs as this
+		 * would complicate the code. Let it simply reseed.
+		 */
+		lrng_sdrng_reset(sdrng);
+		sdrngs[node] = sdrng;
+
+		lrng_pool_inc_numa_node();
+		pr_info("secondary DRNG for NUMA node %d allocated\n", node);
+	}
+
+	/* Ensure that all NUMA nodes receive changed memory here. */
+	mb();
+
+	if (!cmpxchg(&lrng_sdrng, NULL, sdrngs))
+		goto unlock;
+
+err:
+	for_each_online_node(node) {
+		struct lrng_sdrng *sdrng = sdrngs[node];
+
+		if (sdrng == lrng_sdrng_init)
+			continue;
+
+		if (sdrng) {
+			sdrng->crypto_cb->lrng_drng_dealloc(sdrng->sdrng);
+			kfree(sdrng);
+		}
+	}
+	kfree(sdrngs);
+
+unlock:
+	mutex_unlock(&lrng_crypto_cb_update);
+}
+
+static DECLARE_WORK(lrng_drngs_numa_alloc_work, _lrng_drngs_numa_alloc);
+
+void lrng_drngs_numa_alloc(void)
+{
+	schedule_work(&lrng_drngs_numa_alloc_work);
+}
-- 
2.23.0





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v26 03/12] LRNG - sysctls and /proc interface
  2019-11-23 20:08   ` [PATCH v26 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
  2019-11-23 20:10     ` [PATCH v26 01/12] Linux Random Number Generator Stephan Müller
  2019-11-23 20:10     ` [PATCH v26 02/12] LRNG - allocate one SDRNG instance per NUMA node Stephan Müller
@ 2019-11-23 20:11     ` Stephan Müller
  2019-11-23 20:11     ` [PATCH v26 04/12] LRNG - add switchable DRNG support Stephan Müller
                       ` (9 subsequent siblings)
  12 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-23 20:11 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap

The LRNG sysctl interface provides the same controls as the existing
/dev/random implementation. These sysctls behave identically and are
implemented identically. The goal is to allow a possible merge of the
existing /dev/random implementation with this implementation which
implies that this patch tries have a very close similarity. Yet, all
sysctls are documented at [1].

In addition, it provides the file lrng_type which provides details about
the LRNG:

- is the TRNG present

- the name of the DRNG that produces the random numbers for /dev/random,
/dev/urandom, getrandom(2)

- the hash used to produce random numbers from the entropy pool

- the number of secondary DRNG instances

- indicator whether the LRNG operates SP800-90B compliant

- indicator whether a high-resolution timer is identified - only with a
high-resolution timer the interrupt noise source will deliver sufficient
entropy

- indicator whether the LRNG has been minimally seeded (i.e. is the
secondary DRNG seeded with at least 128 bits of of entropy)

- indicator whether the LRNG has been fully seeded (i.e. is the
secondary DRNG seeded with at least 256 bits of entropy)

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

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Makefile          |   1 +
 drivers/char/lrng/lrng_interfaces.c |   1 -
 drivers/char/lrng/lrng_internal.h   |   4 +
 drivers/char/lrng/lrng_proc.c       | 179 ++++++++++++++++++++++++++++
 4 files changed, 184 insertions(+), 1 deletion(-)
 create mode 100644 drivers/char/lrng/lrng_proc.c

diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index a00cddb45773..b6240b73e33d 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -9,3 +9,4 @@ obj-y				+= lrng_pool.o lrng_aux.o \
 				   lrng_interfaces.o \
 
 obj-$(CONFIG_NUMA)		+= lrng_numa.o
+obj-$(CONFIG_SYSCTL)		+= lrng_proc.o
diff --git a/drivers/char/lrng/lrng_interfaces.c b/drivers/char/lrng/lrng_interfaces.c
index 39fc3282843e..11a810c09720 100644
--- a/drivers/char/lrng/lrng_interfaces.c
+++ b/drivers/char/lrng/lrng_interfaces.c
@@ -43,7 +43,6 @@ static DECLARE_WAIT_QUEUE_HEAD(lrng_write_wait);
 static DECLARE_WAIT_QUEUE_HEAD(lrng_init_wait);
 static struct fasync_struct *fasync;
 
-struct ctl_table random_table[];
 /********************************** Helper ***********************************/
 
 /* Is the primary DRNG seed level too low? */
diff --git a/drivers/char/lrng/lrng_internal.h b/drivers/char/lrng/lrng_internal.h
index fb7890939089..cca6e3580030 100644
--- a/drivers/char/lrng/lrng_internal.h
+++ b/drivers/char/lrng/lrng_internal.h
@@ -110,7 +110,11 @@ void lrng_cc20_init_state(struct chacha20_state *state);
 
 /********************************** /proc *************************************/
 
+#ifdef CONFIG_SYSCTL
+void lrng_pool_inc_numa_node(void);
+#else
 static inline void lrng_pool_inc_numa_node(void) { }
+#endif
 
 /****************************** LRNG interfaces *******************************/
 
diff --git a/drivers/char/lrng/lrng_proc.c b/drivers/char/lrng/lrng_proc.c
new file mode 100644
index 000000000000..408bbbf4fa4e
--- /dev/null
+++ b/drivers/char/lrng/lrng_proc.c
@@ -0,0 +1,179 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG proc and sysctl interfaces
+ *
+ * Copyright (C) 2016 - 2019, Stephan Mueller <smueller@chronox.de>
+ */
+
+#include <linux/lrng.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/sysctl.h>
+#include <linux/uuid.h>
+
+#include "lrng_internal.h"
+
+/*
+ * This function is used to return both the bootid UUID, and random
+ * UUID.  The difference is in whether table->data is NULL; if it is,
+ * then a new UUID is generated and returned to the user.
+ *
+ * If the user accesses this via the proc interface, the UUID will be
+ * returned as an ASCII string in the standard UUID format; if via the
+ * sysctl system call, as 16 bytes of binary data.
+ */
+static int lrng_proc_do_uuid(struct ctl_table *table, int write,
+			     void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	struct ctl_table fake_table;
+	unsigned char buf[64], tmp_uuid[16], *uuid;
+
+	uuid = table->data;
+	if (!uuid) {
+		uuid = tmp_uuid;
+		generate_random_uuid(uuid);
+	} else {
+		static DEFINE_SPINLOCK(bootid_spinlock);
+
+		spin_lock(&bootid_spinlock);
+		if (!uuid[8])
+			generate_random_uuid(uuid);
+		spin_unlock(&bootid_spinlock);
+	}
+
+	sprintf(buf, "%pU", uuid);
+
+	fake_table.data = buf;
+	fake_table.maxlen = sizeof(buf);
+
+	return proc_dostring(&fake_table, write, buffer, lenp, ppos);
+}
+
+static int lrng_proc_do_entropy(struct ctl_table *table, int write,
+				void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	struct ctl_table fake_table;
+	int entropy_count;
+
+	entropy_count = lrng_avail_entropy();
+
+	fake_table.data = &entropy_count;
+	fake_table.maxlen = sizeof(entropy_count);
+
+	return proc_dointvec(&fake_table, write, buffer, lenp, ppos);
+}
+
+static int lrng_sysctl_poolsize = LRNG_POOL_SIZE_BITS;
+static int lrng_min_read_thresh = LRNG_POOL_WORD_BITS;
+static int lrng_min_write_thresh;
+static int lrng_max_read_thresh = LRNG_POOL_SIZE_BITS;
+static int lrng_max_write_thresh = LRNG_POOL_SIZE_BITS;
+static char lrng_sysctl_bootid[16];
+static int lrng_sdrng_reseed_max_min;
+
+struct ctl_table random_table[] = {
+	{
+		.procname	= "poolsize",
+		.data		= &lrng_sysctl_poolsize,
+		.maxlen		= sizeof(int),
+		.mode		= 0444,
+		.proc_handler	= proc_dointvec,
+	},
+	{
+		.procname	= "entropy_avail",
+		.maxlen		= sizeof(int),
+		.mode		= 0444,
+		.proc_handler	= lrng_proc_do_entropy,
+	},
+	{
+		.procname	= "read_wakeup_threshold",
+		.data		= &lrng_read_wakeup_bits,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec_minmax,
+		.extra1		= &lrng_min_read_thresh,
+		.extra2		= &lrng_max_read_thresh,
+	},
+	{
+		.procname	= "write_wakeup_threshold",
+		.data		= &lrng_write_wakeup_bits,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec_minmax,
+		.extra1		= &lrng_min_write_thresh,
+		.extra2		= &lrng_max_write_thresh,
+	},
+	{
+		.procname	= "boot_id",
+		.data		= &lrng_sysctl_bootid,
+		.maxlen		= 16,
+		.mode		= 0444,
+		.proc_handler	= lrng_proc_do_uuid,
+	},
+	{
+		.procname	= "uuid",
+		.maxlen		= 16,
+		.mode		= 0444,
+		.proc_handler	= lrng_proc_do_uuid,
+	},
+	{
+		.procname       = "urandom_min_reseed_secs",
+		.data           = &lrng_sdrng_reseed_max_time,
+		.maxlen         = sizeof(int),
+		.mode           = 0644,
+		.proc_handler   = proc_dointvec,
+		.extra1		= &lrng_sdrng_reseed_max_min,
+	},
+	{ }
+};
+
+/* Number of online DRNGs */
+static u32 numa_drngs = 1;
+
+void lrng_pool_inc_numa_node(void)
+{
+	numa_drngs++;
+}
+
+static int lrng_proc_type_show(struct seq_file *m, void *v)
+{
+	struct lrng_sdrng *lrng_sdrng_init = lrng_sdrng_init_instance();
+	unsigned long flags = 0;
+	unsigned char buf[300];
+
+	lrng_sdrng_lock(lrng_sdrng_init, &flags);
+	snprintf(buf, sizeof(buf),
+#ifdef CONFIG_LRNG_TRNG_SUPPORT
+		 "TRNG present: true\n"
+#else
+		 "TRNG present: false\n"
+#endif
+		 "DRNG name: %s\n"
+		 "Hash for reading entropy pool: %s\n"
+		 "DRNG security strength: %d bits\n"
+		 "number of secondary DRNG instances: %u\n"
+		 "SP800-90B compliance: %s\n"
+		 "High-resolution timer: %s\n"
+		 "LRNG minimally seeded: %s\n"
+		 "LRNG fully seeded: %s\n",
+		 lrng_sdrng_init->crypto_cb->lrng_drng_name(),
+		 lrng_sdrng_init->crypto_cb->lrng_hash_name(),
+		 LRNG_DRNG_SECURITY_STRENGTH_BITS, numa_drngs,
+		 lrng_sp80090b_compliant() ? "true" : "false",
+		 lrng_pool_highres_timer() ? "true" : "false",
+		 lrng_state_min_seeded() ? "true" : "false",
+		 lrng_state_fully_seeded() ? "true" : "false");
+	lrng_sdrng_unlock(lrng_sdrng_init, &flags);
+
+	seq_write(m, buf, strlen(buf));
+
+	return 0;
+}
+
+static int __init lrng_proc_type_init(void)
+{
+	proc_create_single("lrng_type", 0444, NULL, &lrng_proc_type_show);
+	return 0;
+}
+
+module_init(lrng_proc_type_init);
-- 
2.23.0





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v26 04/12] LRNG - add switchable DRNG support
  2019-11-23 20:08   ` [PATCH v26 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                       ` (2 preceding siblings ...)
  2019-11-23 20:11     ` [PATCH v26 03/12] LRNG - sysctls and /proc interface Stephan Müller
@ 2019-11-23 20:11     ` Stephan Müller
  2019-11-23 20:31     ` [PATCH v26 05/12] crypto: DRBG - externalize DRBG functions for LRNG Stephan Müller
                       ` (8 subsequent siblings)
  12 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-23 20:11 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap

The DRNG switch support allows replacing the DRNG mechanism of the
LRNG. The switching support rests on the interface definition of
include/linux/lrng.h. A new DRNG is implemented by filling in the
interface defined in this header file.

In addition to the DRNG, the extension also has to provide a hash
implementation that is used to hash the entropy pool for random number
extraction.

Note: It is permissible to implement a DRNG whose operations may sleep.
However, the hash function must not sleep.

The switchable DRNG support allows replacing the DRNG at runtime.
However, only one DRNG extension is allowed to be loaded at any given
time. Before replacing it with another DRNG implementation, the possibly
existing DRNG extension must be unloaded.

The switchable DRNG extension activates the new DRNG during load time.
It is expected, however, that such a DRNG switch would be done only once
by an administrator to load the intended DRNG implementation.

It is permissible to compile DRNG extensions either as kernel modules or
statically. The initialization of the DRNG extension should be performed
with a late_initcall to ensure the extension is available when user
space starts but after all other initialization completed.
The initialization is performed by registering the function call data
structure with the lrng_set_drng_cb function. In order to unload the
DRNG extension, lrng_set_drng_cb must be invoked with the NULL
parameter.

The DRNG extension should always provide a security strength that is at
least as strong as LRNG_DRNG_SECURITY_STRENGTH_BITS.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Kconfig       |   7 ++
 drivers/char/lrng/Makefile      |   1 +
 drivers/char/lrng/lrng_switch.c | 185 ++++++++++++++++++++++++++++++++
 3 files changed, 193 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_switch.c

diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
index 1ba10fd421f3..c6e8eafd836c 100644
--- a/drivers/char/lrng/Kconfig
+++ b/drivers/char/lrng/Kconfig
@@ -52,4 +52,11 @@ config LRNG_POOL_SIZE
 	default 4 if LRNG_POOL_SIZE_65536
 	default 5 if LRNG_POOL_SIZE_131072
 
+menuconfig LRNG_DRNG_SWITCH
+	bool "Support DRNG runtime switching"
+	help
+	  The Linux RNG per default uses a ChaCha20 DRNG that is
+	  accessible via the external interfaces. With this configuration
+	  option other DRNGs can be selected and loaded at runtime.
+
 endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index b6240b73e33d..6bac97638767 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -10,3 +10,4 @@ obj-y				+= lrng_pool.o lrng_aux.o \
 
 obj-$(CONFIG_NUMA)		+= lrng_numa.o
 obj-$(CONFIG_SYSCTL)		+= lrng_proc.o
+obj-$(CONFIG_LRNG_DRNG_SWITCH)	+= lrng_switch.o
diff --git a/drivers/char/lrng/lrng_switch.c b/drivers/char/lrng/lrng_switch.c
new file mode 100644
index 000000000000..1e91a0d6df08
--- /dev/null
+++ b/drivers/char/lrng/lrng_switch.c
@@ -0,0 +1,185 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG DRNG switching support
+ *
+ * Copyright (C) 2016 - 2019, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/lrng.h>
+
+#include "lrng_internal.h"
+
+static void lrng_sdrng_switch(struct lrng_sdrng *sdrng_store,
+			      const struct lrng_crypto_cb *cb, int node)
+{
+	const struct lrng_crypto_cb *old_cb;
+	unsigned long flags = 0;
+	int ret;
+	u8 seed[LRNG_DRNG_SECURITY_STRENGTH_BYTES];
+	void *new_sdrng =
+			cb->lrng_drng_alloc(LRNG_DRNG_SECURITY_STRENGTH_BYTES);
+	void *old_sdrng, *new_hash = NULL, *old_hash = NULL;
+	bool sl = false, reset_sdrng = !lrng_get_available();
+
+	if (IS_ERR(new_sdrng)) {
+		pr_warn("could not allocate new secondary DRNG for NUMA node "
+			"%d (%ld)\n", node, PTR_ERR(new_sdrng));
+		return;
+	}
+
+#ifndef CONFIG_LRNG_TRNG_SUPPORT
+	new_hash = cb->lrng_hash_alloc(seed, sizeof(seed));
+#endif	/* CONFIG_LRNG_TRNG_SUPPORT */
+	if (IS_ERR(new_hash)) {
+		pr_warn("could not allocate new LRNG pool hash (%ld)\n",
+			PTR_ERR(new_hash));
+		cb->lrng_drng_dealloc(new_sdrng);
+		return;
+	}
+
+	lrng_sdrng_lock(sdrng_store, &flags);
+
+	/*
+	 * Pull from existing DRNG to seed new DRNG regardless of seed status
+	 * of old DRNG -- the entropy state for the secondary DRNG is left
+	 * unchanged which implies that als the new DRNG is reseeded when deemed
+	 * necessary. This seeding of the new DRNG shall only ensure that the
+	 * new DRNG has the same entropy as the old DRNG.
+	 */
+	ret = sdrng_store->crypto_cb->lrng_drng_generate_helper(
+				sdrng_store->sdrng, seed, sizeof(seed));
+	lrng_sdrng_unlock(sdrng_store, &flags);
+
+	if (ret < 0) {
+		reset_sdrng = true;
+		pr_warn("getting random data from secondary DRNG failed for "
+			"NUMA node %d (%d)\n", node, ret);
+	} else {
+		/* seed new DRNG with data */
+		ret = cb->lrng_drng_seed_helper(new_sdrng, seed, ret);
+		if (ret < 0) {
+			reset_sdrng = true;
+			pr_warn("seeding of new secondary DRNG failed for NUMA "
+				"node %d (%d)\n", node, ret);
+		} else {
+			pr_debug("seeded new secondary DRNG of NUMA node %d "
+				 "instance from old secondary DRNG instance\n",
+				 node);
+		}
+	}
+
+	mutex_lock(&sdrng_store->lock);
+	/*
+	 * If we switch the secondary DRNG from the initial ChaCha20 DRNG to
+	 * something else, there is a lock transition from spin lock to mutex
+	 * (see lrng_sdrng_is_atomic and how the lock is taken in
+	 * lrng_sdrng_lock). Thus, we need to take both locks during the
+	 * transition phase.
+	 */
+	if (lrng_sdrng_is_atomic(sdrng_store)) {
+		spin_lock_irqsave(&sdrng_store->spin_lock, flags);
+		sl = true;
+	}
+
+	if (reset_sdrng)
+		lrng_sdrng_reset(sdrng_store);
+
+	old_sdrng = sdrng_store->sdrng;
+	old_cb = sdrng_store->crypto_cb;
+	sdrng_store->sdrng = new_sdrng;
+	sdrng_store->crypto_cb = cb;
+
+	if (new_hash) {
+		old_hash = sdrng_store->hash;
+		sdrng_store->hash = new_hash;
+		pr_info("Entropy pool read-hash allocated for DRNG for NUMA "
+			"node %d\n", node);
+	}
+
+	if (sl)
+		spin_unlock_irqrestore(&sdrng_store->spin_lock, flags);
+	mutex_unlock(&sdrng_store->lock);
+
+	/* Secondary ChaCha20 serves as atomic instance left untouched. */
+	if (old_sdrng != &secondary_chacha20) {
+		old_cb->lrng_drng_dealloc(old_sdrng);
+		if (old_hash)
+			old_cb->lrng_hash_dealloc(old_hash);
+	}
+
+	pr_info("secondary DRNG of NUMA node %d switched\n", node);
+}
+
+/**
+ * Switch the existing DRNG instances with new using the new crypto callbacks.
+ * The caller must hold the lrng_crypto_cb_update lock.
+ */
+static int lrng_drngs_switch(const struct lrng_crypto_cb *cb)
+{
+	struct lrng_sdrng **lrng_sdrng = lrng_sdrng_instances();
+	struct lrng_sdrng *lrng_sdrng_init = lrng_sdrng_init_instance();
+	int ret = lrng_trng_switch(cb);
+
+	if (ret)
+		return ret;
+
+	/* Update secondary DRNG */
+	if (lrng_sdrng) {
+		u32 node;
+
+		for_each_online_node(node) {
+			if (lrng_sdrng[node])
+				lrng_sdrng_switch(lrng_sdrng[node], cb, node);
+		}
+	} else
+		lrng_sdrng_switch(lrng_sdrng_init, cb, 0);
+
+	lrng_set_available();
+
+	return 0;
+}
+
+/**
+ * lrng_set_drng_cb - Register new cryptographic callback functions for DRNG
+ * The registering implies that all old DRNG states are replaced with new
+ * DRNG states.
+ * @cb: Callback functions to be registered -- if NULL, use the default
+ *	callbacks pointing to the ChaCha20 DRNG.
+ * @return: 0 on success, < 0 on error
+ */
+int lrng_set_drng_cb(const struct lrng_crypto_cb *cb)
+{
+	struct lrng_sdrng *lrng_sdrng_init = lrng_sdrng_init_instance();
+	int ret;
+
+	if (!cb)
+		cb = &lrng_cc20_crypto_cb;
+
+	mutex_lock(&lrng_crypto_cb_update);
+
+	/*
+	 * If a callback other than the default is set, allow it only to be
+	 * set back to the default callback. This ensures that multiple
+	 * different callbacks can be registered at the same time. If a
+	 * callback different from the current callback and the default
+	 * callback shall be set, the current callback must be deregistered
+	 * (e.g. the kernel module providing it must be unloaded) and the new
+	 * implementation can be registered.
+	 */
+	if ((cb != &lrng_cc20_crypto_cb) &&
+	    (lrng_sdrng_init->crypto_cb != &lrng_cc20_crypto_cb)) {
+		pr_warn("disallow setting new cipher callbacks, unload the old "
+			"callbacks first!\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	ret = lrng_drngs_switch(cb);
+
+out:
+	mutex_unlock(&lrng_crypto_cb_update);
+	return ret;
+}
+EXPORT_SYMBOL(lrng_set_drng_cb);
-- 
2.23.0





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v26 05/12] crypto: DRBG - externalize DRBG functions for LRNG
  2019-11-23 20:08   ` [PATCH v26 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                       ` (3 preceding siblings ...)
  2019-11-23 20:11     ` [PATCH v26 04/12] LRNG - add switchable DRNG support Stephan Müller
@ 2019-11-23 20:31     ` Stephan Müller
  2019-11-23 20:32     ` [PATCH v26 06/12] LRNG - add SP800-90A DRBG extension Stephan Müller
                       ` (7 subsequent siblings)
  12 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-23 20:31 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap

This patch allows several DRBG functions to be called by the LRNG kernel
code paths outside the drbg.c file.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 crypto/drbg.c         | 16 ++++++++++------
 include/crypto/drbg.h |  7 +++++++
 2 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/crypto/drbg.c b/crypto/drbg.c
index b6929eb5f565..5561dd0f09e1 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -113,7 +113,7 @@
  * the SHA256 / AES 256 over other ciphers. Thus, the favored
  * DRBGs are the latest entries in this array.
  */
-static const struct drbg_core drbg_cores[] = {
+const struct drbg_core drbg_cores[] = {
 #ifdef CONFIG_CRYPTO_DRBG_CTR
 	{
 		.flags = DRBG_CTR | DRBG_STRENGTH128,
@@ -190,6 +190,7 @@ static const struct drbg_core drbg_cores[] = {
 	},
 #endif /* CONFIG_CRYPTO_DRBG_HMAC */
 };
+EXPORT_SYMBOL(drbg_cores);
 
 static int drbg_uninstantiate(struct drbg_state *drbg);
 
@@ -205,7 +206,7 @@ static int drbg_uninstantiate(struct drbg_state *drbg);
  * Return: normalized strength in *bytes* value or 32 as default
  *	   to counter programming errors
  */
-static inline unsigned short drbg_sec_strength(drbg_flag_t flags)
+unsigned short drbg_sec_strength(drbg_flag_t flags)
 {
 	switch (flags & DRBG_STRENGTH_MASK) {
 	case DRBG_STRENGTH128:
@@ -218,6 +219,7 @@ static inline unsigned short drbg_sec_strength(drbg_flag_t flags)
 		return 32;
 	}
 }
+EXPORT_SYMBOL(drbg_sec_strength);
 
 /*
  * FIPS 140-2 continuous self test for the noise source
@@ -1202,7 +1204,7 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
 }
 
 /* Free all substructures in a DRBG state without the DRBG state structure */
-static inline void drbg_dealloc_state(struct drbg_state *drbg)
+void drbg_dealloc_state(struct drbg_state *drbg)
 {
 	if (!drbg)
 		return;
@@ -1223,12 +1225,13 @@ static inline void drbg_dealloc_state(struct drbg_state *drbg)
 		drbg->fips_primed = false;
 	}
 }
+EXPORT_SYMBOL(drbg_dealloc_state);
 
 /*
  * Allocate all sub-structures for a DRBG state.
  * The DRBG state structure must already be allocated.
  */
-static inline int drbg_alloc_state(struct drbg_state *drbg)
+int drbg_alloc_state(struct drbg_state *drbg)
 {
 	int ret = -ENOMEM;
 	unsigned int sb_size = 0;
@@ -1307,6 +1310,7 @@ static inline int drbg_alloc_state(struct drbg_state *drbg)
 	drbg_dealloc_state(drbg);
 	return ret;
 }
+EXPORT_SYMBOL(drbg_alloc_state);
 
 /*************************************************************************
  * DRBG interface functions
@@ -1874,8 +1878,7 @@ static int drbg_kcapi_sym_ctr(struct drbg_state *drbg,
  *
  * return: flags
  */
-static inline void drbg_convert_tfm_core(const char *cra_driver_name,
-					 int *coreref, bool *pr)
+void drbg_convert_tfm_core(const char *cra_driver_name, int *coreref, bool *pr)
 {
 	int i = 0;
 	size_t start = 0;
@@ -1902,6 +1905,7 @@ static inline void drbg_convert_tfm_core(const char *cra_driver_name,
 		}
 	}
 }
+EXPORT_SYMBOL(drbg_convert_tfm_core);
 
 static int drbg_kcapi_init(struct crypto_tfm *tfm)
 {
diff --git a/include/crypto/drbg.h b/include/crypto/drbg.h
index 8c9af21efce1..c63b20375235 100644
--- a/include/crypto/drbg.h
+++ b/include/crypto/drbg.h
@@ -282,4 +282,11 @@ enum drbg_prefixes {
 	DRBG_PREFIX3
 };
 
+extern int drbg_alloc_state(struct drbg_state *drbg);
+extern void drbg_dealloc_state(struct drbg_state *drbg);
+extern void drbg_convert_tfm_core(const char *cra_driver_name, int *coreref,
+				  bool *pr);
+extern const struct drbg_core drbg_cores[];
+extern unsigned short drbg_sec_strength(drbg_flag_t flags);
+
 #endif /* _DRBG_H */
-- 
2.23.0





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v26 06/12] LRNG - add SP800-90A DRBG extension
  2019-11-23 20:08   ` [PATCH v26 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                       ` (4 preceding siblings ...)
  2019-11-23 20:31     ` [PATCH v26 05/12] crypto: DRBG - externalize DRBG functions for LRNG Stephan Müller
@ 2019-11-23 20:32     ` Stephan Müller
  2019-11-23 20:32     ` [PATCH v26 07/12] LRNG - add kernel crypto API PRNG extension Stephan Müller
                       ` (6 subsequent siblings)
  12 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-23 20:32 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap

Using the LRNG switchable DRNG support, the SP800-90A DRBG extension is
implemented.

The DRBG uses the kernel crypto API DRBG implementation. In addition, it
uses the kernel crypto API SHASH support to provide the hashing
operation.

The DRBG supports the choice of either a CTR DRBG using AES-256, HMAC
DRBG with SHA-512 core or Hash DRBG with SHA-512 core. The used core can
be selected with the module parameter lrng_drbg_type. The default is the
CTR DRBG.

When compiling the DRBG extension statically, the DRBG is loaded at
late_initcall stage which implies that with the start of user space, the
user space interfaces of getrandom(2), /dev/random and /dev/urandom
provide random data produced by an SP800-90A DRBG.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Kconfig     |  11 ++
 drivers/char/lrng/Makefile    |   1 +
 drivers/char/lrng/lrng_drbg.c | 261 ++++++++++++++++++++++++++++++++++
 3 files changed, 273 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_drbg.c

diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
index c6e8eafd836c..dcdf4ef83da5 100644
--- a/drivers/char/lrng/Kconfig
+++ b/drivers/char/lrng/Kconfig
@@ -59,4 +59,15 @@ menuconfig LRNG_DRNG_SWITCH
 	  accessible via the external interfaces. With this configuration
 	  option other DRNGs can be selected and loaded at runtime.
 
+if LRNG_DRNG_SWITCH
+config LRNG_DRBG
+	tristate "SP800-90A support for the LRNG"
+	select CRYPTO_DRBG_MENU
+	select CRYPTO_CMAC if CRYPTO_DRBG_CTR
+	help
+	  Enable the SP800-90A DRBG support for the LRNG. Once the
+	  module is loaded, output from /dev/random, /dev/urandom,
+	  getrandom(2), or get_random_bytes is provided by a DRBG.
+endif # LRNG_DRNG_SWITCH
+
 endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index 6bac97638767..e3a704b3466c 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -11,3 +11,4 @@ obj-y				+= lrng_pool.o lrng_aux.o \
 obj-$(CONFIG_NUMA)		+= lrng_numa.o
 obj-$(CONFIG_SYSCTL)		+= lrng_proc.o
 obj-$(CONFIG_LRNG_DRNG_SWITCH)	+= lrng_switch.o
+obj-$(CONFIG_LRNG_DRBG)		+= lrng_drbg.o
diff --git a/drivers/char/lrng/lrng_drbg.c b/drivers/char/lrng/lrng_drbg.c
new file mode 100644
index 000000000000..3b5314f399a2
--- /dev/null
+++ b/drivers/char/lrng/lrng_drbg.c
@@ -0,0 +1,261 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * Backend for the LRNG providing the cryptographic primitives using the
+ * kernel crypto API and its DRBG.
+ *
+ * Copyright (C) 2016 - 2019, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <crypto/drbg.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/lrng.h>
+
+/*
+ * Define a DRBG plus a hash / MAC used to extract data from the entropy pool.
+ * For LRNG_HASH_NAME you can use a hash or a MAC (HMAC or CMAC) of your choice
+ * (Note, you should use the suggested selections below -- using SHA-1 or MD5
+ * is not wise). The idea is that the used cipher primitive can be selected to
+ * be the same as used for the DRBG. I.e. the LRNG only uses one cipher
+ * primitive using the same cipher implementation with the options offered in
+ * the following. This means, if the CTR DRBG is selected and AES-NI is present,
+ * both the CTR DRBG and the selected cmac(aes) use AES-NI.
+ *
+ * The security strengths of the DRBGs are all 256 bits according to
+ * SP800-57 section 5.6.1.
+ *
+ * This definition is allowed to be changed.
+ */
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+static unsigned int lrng_drbg_type = 0;
+#elif defined CONFIG_CRYPTO_DRBG_HMAC
+static unsigned int lrng_drbg_type = 1;
+#elif defined CONFIG_CRYPTO_DRBG_HASH
+static unsigned int lrng_drbg_type = 2;
+#else
+#error "Unknown DRBG in use"
+#endif
+
+/* The parameter must be r/o in sysfs as otherwise races appear. */
+module_param(lrng_drbg_type, uint, 0444);
+MODULE_PARM_DESC(lrng_drbg_type, "DRBG type used for LRNG (0->CTR_DRBG, "
+				 "1->HMAC_DRBG, 2->Hash_DRBG)");
+
+struct lrng_drbg {
+	const char *hash_name;
+	const char *drbg_core;
+};
+
+static const struct lrng_drbg lrng_drbg_types[] = {
+	{	/* CTR_DRBG with AES-256 using derivation function */
+		.hash_name = "cmac(aes)",
+		.drbg_core = "drbg_nopr_ctr_aes256",
+	}, {	/* HMAC_DRBG with SHA-512 */
+		.hash_name = "sha512",
+		.drbg_core = "drbg_nopr_hmac_sha512",
+	}, {	/* Hash_DRBG with SHA-512 using derivation function */
+		.hash_name = "sha512",
+		.drbg_core = "drbg_nopr_sha512"
+	}
+};
+
+struct lrng_hash_info {
+	struct shash_desc shash;
+	char ctx[];
+};
+
+static int lrng_drbg_drng_seed_helper(void *drng, const u8 *inbuf, u32 inbuflen)
+{
+	struct drbg_state *drbg = (struct drbg_state *)drng;
+	LIST_HEAD(seedlist);
+	struct drbg_string data;
+	int ret;
+
+	drbg_string_fill(&data, inbuf, inbuflen);
+	list_add_tail(&data.list, &seedlist);
+	ret = drbg->d_ops->update(drbg, &seedlist, drbg->seeded);
+
+	if (ret >= 0)
+		drbg->seeded = true;
+
+	return ret;
+}
+
+static int lrng_drbg_drng_generate_helper(void *drng, u8 *outbuf, u32 outbuflen)
+{
+	struct drbg_state *drbg = (struct drbg_state *)drng;
+
+	return drbg->d_ops->generate(drbg, outbuf, outbuflen, NULL);
+}
+
+static void *lrng_drbg_drng_alloc(u32 sec_strength)
+{
+	struct drbg_state *drbg;
+	int coreref = -1;
+	bool pr = false;
+	int ret;
+
+	drbg_convert_tfm_core(lrng_drbg_types[lrng_drbg_type].drbg_core,
+			      &coreref, &pr);
+	if (coreref < 0)
+		return ERR_PTR(-EFAULT);
+
+	drbg = kzalloc(sizeof(struct drbg_state), GFP_KERNEL);
+	if (!drbg)
+		return ERR_PTR(-ENOMEM);
+
+	drbg->core = &drbg_cores[coreref];
+	drbg->seeded = false;
+	ret = drbg_alloc_state(drbg);
+	if (ret)
+		goto err;
+
+	if (sec_strength > drbg_sec_strength(drbg->core->flags)) {
+		pr_err("Security strength of DRBG (%u bits) lower than "
+		       "requested by LRNG (%u bits)\n",
+			drbg_sec_strength(drbg->core->flags) * 8,
+			sec_strength * 8);
+		goto dealloc;
+	}
+
+	if (sec_strength < drbg_sec_strength(drbg->core->flags))
+		pr_warn("Security strength of DRBG (%u bits) higher than "
+			"requested by LRNG (%u bits)\n",
+			drbg_sec_strength(drbg->core->flags) * 8,
+			sec_strength * 8);
+
+	pr_info("DRBG with %s core allocated\n", drbg->core->backend_cra_name);
+
+	return drbg;
+
+dealloc:
+	if (drbg->d_ops)
+		drbg->d_ops->crypto_fini(drbg);
+	drbg_dealloc_state(drbg);
+err:
+	kfree(drbg);
+	return ERR_PTR(-EINVAL);
+}
+
+static void lrng_drbg_drng_dealloc(void *drng)
+{
+	struct drbg_state *drbg = (struct drbg_state *)drng;
+
+	drbg_dealloc_state(drbg);
+	kzfree(drbg);
+	pr_info("DRBG deallocated\n");
+}
+
+static void *lrng_drbg_hash_alloc(const u8 *key, u32 keylen)
+{
+	struct lrng_hash_info *lrng_hash;
+	struct crypto_shash *tfm;
+	int size, ret;
+
+	tfm = crypto_alloc_shash(lrng_drbg_types[lrng_drbg_type].hash_name,
+				 0, 0);
+	if (IS_ERR(tfm)) {
+		pr_err("could not allocate hash %s\n",
+		       lrng_drbg_types[lrng_drbg_type].hash_name);
+		return ERR_CAST(tfm);
+	}
+
+	size = sizeof(struct lrng_hash_info) + crypto_shash_descsize(tfm);
+	lrng_hash = kmalloc(size, GFP_KERNEL);
+	if (!lrng_hash) {
+		crypto_free_shash(tfm);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	lrng_hash->shash.tfm = tfm;
+
+	/* If the used hash is no MAC, ignore the ENOSYS return code */
+	ret = crypto_shash_setkey(tfm, key, keylen);
+	if (ret && ret != -ENOSYS) {
+		pr_err("could not set the key for MAC\n");
+		crypto_free_shash(tfm);
+		kfree(lrng_hash);
+		return ERR_PTR(ret);
+	}
+
+	pr_info("Hash %s allocated\n",
+		lrng_drbg_types[lrng_drbg_type].hash_name);
+
+	return lrng_hash;
+}
+
+static void lrng_drbg_hash_dealloc(void *hash)
+{
+	struct lrng_hash_info *lrng_hash = (struct lrng_hash_info *)hash;
+	struct shash_desc *shash = &lrng_hash->shash;
+	struct crypto_shash *tfm = shash->tfm;
+
+	crypto_free_shash(tfm);
+	kfree(lrng_hash);
+	pr_info("Hash deallocated\n");
+}
+
+static u32 lrng_drbg_hash_digestsize(void *hash)
+{
+	struct lrng_hash_info *lrng_hash = (struct lrng_hash_info *)hash;
+	struct shash_desc *shash = &lrng_hash->shash;
+
+	return crypto_shash_digestsize(shash->tfm);
+}
+
+static int lrng_drbg_hash_buffer(void *hash, const u8 *inbuf, u32 inbuflen,
+				 u8 *digest)
+{
+	struct lrng_hash_info *lrng_hash = (struct lrng_hash_info *)hash;
+	struct shash_desc *shash = &lrng_hash->shash;
+
+	return crypto_shash_digest(shash, inbuf, inbuflen, digest);
+}
+
+static const char *lrng_drbg_name(void)
+{
+	return lrng_drbg_types[lrng_drbg_type].drbg_core;
+}
+
+static const char *lrng_hash_name(void)
+{
+	return lrng_drbg_types[lrng_drbg_type].hash_name;
+}
+
+const static struct lrng_crypto_cb lrng_drbg_crypto_cb = {
+	.lrng_drng_name			= lrng_drbg_name,
+	.lrng_hash_name			= lrng_hash_name,
+	.lrng_drng_alloc		= lrng_drbg_drng_alloc,
+	.lrng_drng_dealloc		= lrng_drbg_drng_dealloc,
+	.lrng_drng_seed_helper		= lrng_drbg_drng_seed_helper,
+	.lrng_drng_generate_helper	= lrng_drbg_drng_generate_helper,
+	.lrng_drng_generate_helper_full	= lrng_drbg_drng_generate_helper,
+	.lrng_hash_alloc		= lrng_drbg_hash_alloc,
+	.lrng_hash_dealloc		= lrng_drbg_hash_dealloc,
+	.lrng_hash_digestsize		= lrng_drbg_hash_digestsize,
+	.lrng_hash_buffer		= lrng_drbg_hash_buffer,
+};
+
+static int __init lrng_drbg_init(void)
+{
+	if (lrng_drbg_type >= ARRAY_SIZE(lrng_drbg_types)) {
+		pr_err("lrng_drbg_type parameter too large (given %u - max: %lu)",
+		       lrng_drbg_type,
+		       (unsigned long)ARRAY_SIZE(lrng_drbg_types) - 1);
+		return -EAGAIN;
+	}
+	return lrng_set_drng_cb(&lrng_drbg_crypto_cb);
+}
+
+static void __exit lrng_drbg_exit(void)
+{
+	lrng_set_drng_cb(NULL);
+}
+
+late_initcall(lrng_drbg_init);
+module_exit(lrng_drbg_exit);
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
+MODULE_DESCRIPTION("Linux Random Number Generator - SP800-90A DRBG backend");
-- 
2.23.0





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v26 07/12] LRNG - add kernel crypto API PRNG extension
  2019-11-23 20:08   ` [PATCH v26 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                       ` (5 preceding siblings ...)
  2019-11-23 20:32     ` [PATCH v26 06/12] LRNG - add SP800-90A DRBG extension Stephan Müller
@ 2019-11-23 20:32     ` Stephan Müller
  2019-11-23 20:33     ` [PATCH v26 08/12] crypto: provide access to a static Jitter RNG state Stephan Müller
                       ` (5 subsequent siblings)
  12 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-23 20:32 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap

Add runtime-pluggable support for all PRNGs that are accessible via
the kernel crypto API, including hardware PRNGs. The PRNG is selected
with the module parameter drng_name where the name must be one that the
kernel crypto API can resolve into an RNG.

This allows using of the kernel crypto API PRNG implementations that
provide an interface to hardware PRNGs. Using this extension,
the LRNG uses the hardware PRNGs to generate random numbers. An
example is the S390 CPACF support providing such a PRNG.

The hash is provided by a kernel crypto API SHASH whose digest size
complies with the seedsize of the PRNG.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Kconfig      |  10 +
 drivers/char/lrng/Makefile     |   1 +
 drivers/char/lrng/lrng_kcapi.c | 328 +++++++++++++++++++++++++++++++++
 3 files changed, 339 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_kcapi.c

diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
index dcdf4ef83da5..03e6e2ec356b 100644
--- a/drivers/char/lrng/Kconfig
+++ b/drivers/char/lrng/Kconfig
@@ -68,6 +68,16 @@ config LRNG_DRBG
 	  Enable the SP800-90A DRBG support for the LRNG. Once the
 	  module is loaded, output from /dev/random, /dev/urandom,
 	  getrandom(2), or get_random_bytes is provided by a DRBG.
+
+config LRNG_KCAPI
+	tristate "Kernel Crypto API support for the LRNG"
+	select CRYPTO_RNG
+	help
+	  Enable the support for generic pseudo-random number
+	  generators offered by the kernel crypto API with the
+	  LRNG. Once the module is loaded, output from /dev/random,
+	  /dev/urandom, getrandom(2), or get_random_bytes is
+	  provided by the selected kernel crypto API RNG.
 endif # LRNG_DRNG_SWITCH
 
 endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index e3a704b3466c..027b6ea51c20 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -12,3 +12,4 @@ obj-$(CONFIG_NUMA)		+= lrng_numa.o
 obj-$(CONFIG_SYSCTL)		+= lrng_proc.o
 obj-$(CONFIG_LRNG_DRNG_SWITCH)	+= lrng_switch.o
 obj-$(CONFIG_LRNG_DRBG)		+= lrng_drbg.o
+obj-$(CONFIG_LRNG_KCAPI)	+= lrng_kcapi.o
diff --git a/drivers/char/lrng/lrng_kcapi.c b/drivers/char/lrng/lrng_kcapi.c
new file mode 100644
index 000000000000..f887447e524d
--- /dev/null
+++ b/drivers/char/lrng/lrng_kcapi.c
@@ -0,0 +1,328 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * Backend for the LRNG providing the cryptographic primitives using the
+ * kernel crypto API.
+ *
+ * Copyright (C) 2018 - 2019, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <crypto/hash.h>
+#include <crypto/rng.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/lrng.h>
+
+static char *drng_name = NULL;
+module_param(drng_name, charp, 0444);
+MODULE_PARM_DESC(drng_name, "Kernel crypto API name of DRNG");
+
+static char *pool_hash = "sha512";
+module_param(pool_hash, charp, 0444);
+MODULE_PARM_DESC(pool_hash,
+		 "Kernel crypto API name of hash or keyed message digest to read the entropy pool");
+
+static char *seed_hash = NULL;
+module_param(seed_hash, charp, 0444);
+MODULE_PARM_DESC(seed_hash,
+		 "Kernel crypto API name of hash with output size equal to seedsize of DRNG to bring seed string to the size required by the DRNG");
+
+struct lrng_hash_info {
+	struct shash_desc shash;
+	char ctx[];
+};
+
+struct lrng_drng_info {
+	struct crypto_rng *kcapi_rng;
+	struct lrng_hash_info *lrng_hash;
+};
+
+static struct lrng_hash_info *_lrng_kcapi_hash_alloc(const char *name)
+{
+	struct lrng_hash_info *lrng_hash;
+	struct crypto_shash *tfm;
+	int size;
+
+	if (!name) {
+		pr_err("Hash name missing\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	tfm = crypto_alloc_shash(name, 0, 0);
+	if (IS_ERR(tfm)) {
+		pr_err("could not allocate hash %s\n", name);
+		return ERR_CAST(tfm);
+	}
+
+	size = sizeof(struct lrng_hash_info) + crypto_shash_descsize(tfm);
+	lrng_hash = kmalloc(size, GFP_KERNEL);
+	if (!lrng_hash) {
+		crypto_free_shash(tfm);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	lrng_hash->shash.tfm = tfm;
+
+	return lrng_hash;
+}
+
+static inline u32 _lrng_kcapi_hash_digestsize(struct lrng_hash_info *lrng_hash)
+{
+	struct shash_desc *shash = &lrng_hash->shash;
+	struct crypto_shash *tfm = shash->tfm;
+
+	return crypto_shash_digestsize(tfm);
+}
+
+static inline void _lrng_kcapi_hash_free(struct lrng_hash_info *lrng_hash)
+{
+	struct shash_desc *shash = &lrng_hash->shash;
+	struct crypto_shash *tfm = shash->tfm;
+
+	crypto_free_shash(tfm);
+	kfree(lrng_hash);
+}
+
+static void *lrng_kcapi_hash_alloc(const u8 *key, u32 keylen)
+{
+	struct lrng_hash_info *lrng_hash;
+	int ret;
+
+	lrng_hash = _lrng_kcapi_hash_alloc(pool_hash);
+	if (IS_ERR(lrng_hash))
+		return ERR_CAST(lrng_hash);
+
+	/* If the used hash is no MAC, ignore the ENOSYS return code */
+	ret = crypto_shash_setkey(lrng_hash->shash.tfm, key, keylen);
+	if (ret && ret != -ENOSYS) {
+		pr_err("could not set the key for MAC\n");
+		_lrng_kcapi_hash_free(lrng_hash);
+		return ERR_PTR(ret);
+	}
+
+	pr_info("Hash %s allocated\n", pool_hash);
+
+	return lrng_hash;
+}
+
+static void lrng_kcapi_hash_dealloc(void *hash)
+{
+	struct lrng_hash_info *lrng_hash = (struct lrng_hash_info *)hash;
+
+	_lrng_kcapi_hash_free(lrng_hash);
+	pr_info("Hash %s deallocated\n", pool_hash);
+}
+
+static u32 lrng_kcapi_hash_digestsize(void *hash)
+{
+	struct lrng_hash_info *lrng_hash = (struct lrng_hash_info *)hash;
+
+	return _lrng_kcapi_hash_digestsize(lrng_hash);
+}
+
+static int lrng_kcapi_hash_buffer(void *hash, const u8 *inbuf, u32 inbuflen,
+				  u8 *digest)
+{
+	struct lrng_hash_info *lrng_hash = (struct lrng_hash_info *)hash;
+	struct shash_desc *shash = &lrng_hash->shash;
+
+	return crypto_shash_digest(shash, inbuf, inbuflen, digest);
+}
+
+static int lrng_kcapi_drng_seed_helper(void *drng, const u8 *inbuf,
+				       u32 inbuflen)
+{
+	struct lrng_drng_info *lrng_drng_info = (struct lrng_drng_info *)drng;
+	struct crypto_rng *kcapi_rng = lrng_drng_info->kcapi_rng;
+	struct lrng_hash_info *lrng_hash = lrng_drng_info->lrng_hash;
+
+	if (lrng_hash) {
+		struct shash_desc *shash = &lrng_hash->shash;
+		u32 digestsize = _lrng_kcapi_hash_digestsize(lrng_hash);
+		u8 digest[64] __aligned(8);
+		int ret;
+
+		BUG_ON(digestsize > sizeof(digest));
+
+		ret = crypto_shash_digest(shash, inbuf, inbuflen, digest);
+		if (ret)
+			return ret;
+
+		ret = crypto_rng_reset(kcapi_rng, digest, digestsize);
+		if (ret)
+			return ret;
+
+		memzero_explicit(digest, digestsize);
+
+		return 0;
+	} else {
+		return crypto_rng_reset(kcapi_rng, inbuf, inbuflen);
+	}
+}
+
+static int lrng_kcapi_drng_generate_helper(void *drng, u8 *outbuf,
+					   u32 outbuflen)
+{
+	struct lrng_drng_info *lrng_drng_info = (struct lrng_drng_info *)drng;
+	struct crypto_rng *kcapi_rng = lrng_drng_info->kcapi_rng;
+	int ret = crypto_rng_get_bytes(kcapi_rng, outbuf, outbuflen);
+
+	if (ret < 0)
+		return ret;
+
+	return outbuflen;
+}
+
+static void *lrng_kcapi_drng_alloc(u32 sec_strength)
+{
+	struct lrng_drng_info *lrng_drng_info;
+	struct crypto_rng *kcapi_rng;
+	int seedsize;
+	void *ret =  ERR_PTR(-ENOMEM);
+
+	if (!drng_name) {
+		pr_err("DRNG name missing\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (!memcmp(drng_name, "drbg", 4)) {
+		pr_err("SP800-90A DRBG cannot be allocated using lrng_kcapi "
+		       "backend, use lrng_drbg backend instead\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (!memcmp(drng_name, "stdrng", 6)) {
+		pr_err("stdrng cannot be allocated using lrng_kcapi backend, "
+		       "it is too unspecific and potentially may allocate the "
+		       "DRBG\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	lrng_drng_info = kmalloc(sizeof(*lrng_drng_info), GFP_KERNEL);
+	if (!lrng_drng_info)
+		return ERR_PTR(-ENOMEM);
+
+	kcapi_rng = crypto_alloc_rng(drng_name, 0, 0);
+	if (IS_ERR(kcapi_rng)) {
+		pr_err("DRNG %s cannot be allocated\n", drng_name);
+		ret = ERR_CAST(kcapi_rng);
+		goto free;
+	}
+	lrng_drng_info->kcapi_rng = kcapi_rng;
+
+	seedsize =  crypto_rng_seedsize(kcapi_rng);
+
+	if (sec_strength > seedsize)
+		pr_info("Seedsize DRNG (%u bits) lower than "
+			"security strength of LRNG noise source (%u bits)\n",
+			crypto_rng_seedsize(kcapi_rng) * 8,
+			sec_strength * 8);
+
+	if (seedsize) {
+		struct lrng_hash_info *lrng_hash;
+
+		if (!seed_hash) {
+			switch (seedsize) {
+			case 32:
+				seed_hash = "sha256";
+				break;
+			case 48:
+				seed_hash = "sha384";
+				break;
+			case 64:
+				seed_hash = "sha512";
+				break;
+			default:
+				pr_err("Seed size %d cannot be processed\n",
+				       seedsize);
+				goto dealloc;
+				break;
+			}
+		}
+
+		lrng_hash = _lrng_kcapi_hash_alloc(seed_hash);
+		if (IS_ERR(lrng_hash)) {
+			ret = ERR_CAST(lrng_hash);
+			goto dealloc;
+		}
+
+		if (seedsize != _lrng_kcapi_hash_digestsize(lrng_hash)) {
+			pr_err("Seed hash output size not equal to DRNG seed "
+			       "size\n");
+			_lrng_kcapi_hash_free(lrng_hash);
+			ret = ERR_PTR(-EINVAL);
+			goto dealloc;
+		}
+
+		lrng_drng_info->lrng_hash = lrng_hash;
+
+		pr_info("Seed hash %s allocated\n", seed_hash);
+	} else {
+		lrng_drng_info->lrng_hash = NULL;
+	}
+
+	pr_info("Kernel crypto API DRNG %s allocated\n", drng_name);
+
+	return lrng_drng_info;
+
+dealloc:
+	crypto_free_rng(kcapi_rng);
+free:
+	kfree(lrng_drng_info);
+	return ret;
+}
+
+static void lrng_kcapi_drng_dealloc(void *drng)
+{
+	struct lrng_drng_info *lrng_drng_info = (struct lrng_drng_info *)drng;
+	struct crypto_rng *kcapi_rng = lrng_drng_info->kcapi_rng;
+	struct lrng_hash_info *lrng_hash = lrng_drng_info->lrng_hash;
+
+	crypto_free_rng(kcapi_rng);
+	if (lrng_hash) {
+		_lrng_kcapi_hash_free(lrng_hash);
+		pr_info("Seed hash %s deallocated\n", seed_hash);
+	}
+	kfree(lrng_drng_info);
+	pr_info("DRNG %s deallocated\n", drng_name);
+}
+
+static const char *lrng_kcapi_drng_name(void)
+{
+	return drng_name;
+}
+
+static const char *lrng_kcapi_pool_hash(void)
+{
+	return pool_hash;
+}
+
+const static struct lrng_crypto_cb lrng_kcapi_crypto_cb = {
+	.lrng_drng_name			= lrng_kcapi_drng_name,
+	.lrng_hash_name			= lrng_kcapi_pool_hash,
+	.lrng_drng_alloc		= lrng_kcapi_drng_alloc,
+	.lrng_drng_dealloc		= lrng_kcapi_drng_dealloc,
+	.lrng_drng_seed_helper		= lrng_kcapi_drng_seed_helper,
+	.lrng_drng_generate_helper	= lrng_kcapi_drng_generate_helper,
+	.lrng_drng_generate_helper_full	= lrng_kcapi_drng_generate_helper,
+	.lrng_hash_alloc		= lrng_kcapi_hash_alloc,
+	.lrng_hash_dealloc		= lrng_kcapi_hash_dealloc,
+	.lrng_hash_digestsize		= lrng_kcapi_hash_digestsize,
+	.lrng_hash_buffer		= lrng_kcapi_hash_buffer,
+};
+
+static int __init lrng_kcapi_init(void)
+{
+	return lrng_set_drng_cb(&lrng_kcapi_crypto_cb);
+}
+static void __exit lrng_kcapi_exit(void)
+{
+	lrng_set_drng_cb(NULL);
+}
+
+late_initcall(lrng_kcapi_init);
+module_exit(lrng_kcapi_exit);
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
+MODULE_DESCRIPTION("Linux Random Number Generator - kernel crypto API DRNG backend");
-- 
2.23.0





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v26 08/12] crypto: provide access to a static Jitter RNG state
  2019-11-23 20:08   ` [PATCH v26 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                       ` (6 preceding siblings ...)
  2019-11-23 20:32     ` [PATCH v26 07/12] LRNG - add kernel crypto API PRNG extension Stephan Müller
@ 2019-11-23 20:33     ` Stephan Müller
  2019-11-23 20:34     ` [PATCH v26 09/12] LRNG - add Jitter RNG fast noise source Stephan Müller
                       ` (4 subsequent siblings)
  12 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-23 20:33 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap

To support the LRNG operation which uses the Jitter RNG separately
from the kernel crypto API, at a time where potentially the regular
memory management is not yet initialized, the Jitter RNG needs to
provide a state whose memory is defined at compile time. As only once
instance will ever be needed by the LRNG, define once static memory
block which is solely to be used by the LRNG.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 crypto/jitterentropy.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/crypto/jitterentropy.c b/crypto/jitterentropy.c
index 77fa2120fe0c..3a815495f778 100644
--- a/crypto/jitterentropy.c
+++ b/crypto/jitterentropy.c
@@ -644,3 +644,26 @@ int jent_entropy_init(void)
 
 	return 0;
 }
+
+struct rand_data *jent_lrng_entropy_collector(void)
+{
+	static unsigned char lrng_jent_mem[JENT_MEMORY_SIZE];
+	static struct rand_data lrng_jent_state = {
+		.data		= 0,
+		.old_data	= 0,
+		.prev_time	= 0,
+		.last_delta	= 0,
+		.last_delta2	= 0,
+		.osr		= 1,
+		.mem		= lrng_jent_mem,
+		.memlocation	= 0,
+		.memblocks	= JENT_MEMORY_BLOCKSIZE,
+		.memblocksize	= JENT_MEMORY_BLOCKS,
+		.memaccessloops	= JENT_MEMORY_ACCESSLOOPS,
+	};
+
+	if (jent_entropy_init())
+		return NULL;
+
+	return &lrng_jent_state;
+}
-- 
2.23.0





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v26 09/12] LRNG - add Jitter RNG fast noise source
  2019-11-23 20:08   ` [PATCH v26 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                       ` (7 preceding siblings ...)
  2019-11-23 20:33     ` [PATCH v26 08/12] crypto: provide access to a static Jitter RNG state Stephan Müller
@ 2019-11-23 20:34     ` Stephan Müller
  2019-11-23 20:34     ` [PATCH v26 10/12] LRNG - add TRNG support Stephan Müller
                       ` (3 subsequent siblings)
  12 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-23 20:34 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap

The Jitter RNG fast noise source implemented as part of the kernel
crypto API is queried for 256 bits of entropy at the time the seed
buffer managed by the LRNG is about to be filled.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Kconfig     | 11 +++++
 drivers/char/lrng/Makefile    |  1 +
 drivers/char/lrng/lrng_jent.c | 88 +++++++++++++++++++++++++++++++++++
 3 files changed, 100 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_jent.c

diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
index 03e6e2ec356b..80fc723c67d2 100644
--- a/drivers/char/lrng/Kconfig
+++ b/drivers/char/lrng/Kconfig
@@ -80,4 +80,15 @@ config LRNG_KCAPI
 	  provided by the selected kernel crypto API RNG.
 endif # LRNG_DRNG_SWITCH
 
+config LRNG_JENT
+	bool "Enable Jitter RNG as LRNG Seed Source"
+	select CRYPTO_JITTERENTROPY
+	help
+	  The Linux RNG may use the Jitter RNG as noise source. Enabling
+	  this option enables the use of the Jitter RNG. Its default
+	  entropy level is 16 bits of entropy per 256 data bits delivered
+	  by the Jitter RNG. This entropy level can be changed at boot
+	  time or at runtime with the lrng_base.jitterrng configuration
+	  variable.
+
 endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index 027b6ea51c20..a87d800c9aae 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -13,3 +13,4 @@ obj-$(CONFIG_SYSCTL)		+= lrng_proc.o
 obj-$(CONFIG_LRNG_DRNG_SWITCH)	+= lrng_switch.o
 obj-$(CONFIG_LRNG_DRBG)		+= lrng_drbg.o
 obj-$(CONFIG_LRNG_KCAPI)	+= lrng_kcapi.o
+obj-$(CONFIG_LRNG_JENT)		+= lrng_jent.o
diff --git a/drivers/char/lrng/lrng_jent.c b/drivers/char/lrng/lrng_jent.c
new file mode 100644
index 000000000000..43114a44b8f5
--- /dev/null
+++ b/drivers/char/lrng/lrng_jent.c
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG Fast Noise Source: Jitter RNG
+ *
+ * Copyright (C) 2016 - 2019, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "lrng_internal.h"
+
+/*
+ * Estimated entropy of data is a 16th of LRNG_DRNG_SECURITY_STRENGTH_BITS.
+ * Albeit a full entropy assessment is provided for the noise source indicating
+ * that it provides high entropy rates and considering that it deactivates
+ * when it detects insufficient hardware, the chosen under estimation of
+ * entropy is considered to be acceptable to all reviewers.
+ */
+static u32 jitterrng = LRNG_DRNG_SECURITY_STRENGTH_BITS>>4;
+module_param(jitterrng, uint, 0644);
+MODULE_PARM_DESC(jitterrng, "Entropy in bits of 256 data bits from Jitter "
+			    "RNG noise source");
+
+/**
+ * Get Jitter RNG entropy
+ *
+ * @outbuf buffer to store entropy
+ * @outbuflen length of buffer
+ * @return > 0 on success where value provides the added entropy in bits
+ *	   0 if no fast source was available
+ */
+struct rand_data;
+struct rand_data *jent_lrng_entropy_collector(void);
+int jent_read_entropy(struct rand_data *ec, unsigned char *data,
+		      unsigned int len);
+static struct rand_data *lrng_jent_state;
+
+u32 lrng_get_jent(u8 *outbuf, unsigned int outbuflen)
+{
+	int ret;
+	u32 ent_bits = jitterrng;
+	unsigned long flags;
+	static DEFINE_SPINLOCK(lrng_jent_lock);
+	static int lrng_jent_initialized = 0;
+
+	spin_lock_irqsave(&lrng_jent_lock, flags);
+
+	if (!ent_bits || (lrng_jent_initialized == -1)) {
+		spin_unlock_irqrestore(&lrng_jent_lock, flags);
+		return 0;
+	}
+
+	if (!lrng_jent_initialized) {
+		lrng_jent_state = jent_lrng_entropy_collector();
+		if (!lrng_jent_state) {
+			jitterrng = 0;
+			lrng_jent_initialized = -1;
+			spin_unlock_irqrestore(&lrng_jent_lock, flags);
+			pr_info("Jitter RNG unusable on current system\n");
+			return 0;
+		}
+		lrng_jent_initialized = 1;
+		pr_debug("Jitter RNG working on current system\n");
+	}
+	ret = jent_read_entropy(lrng_jent_state, outbuf, outbuflen);
+	spin_unlock_irqrestore(&lrng_jent_lock, flags);
+
+	if (ret) {
+		pr_debug("Jitter RNG failed with %d\n", ret);
+		return 0;
+	}
+
+	/* Obtain entropy statement */
+	if (outbuflen != LRNG_DRNG_SECURITY_STRENGTH_BYTES)
+		ent_bits = (ent_bits * outbuflen<<3) /
+			   LRNG_DRNG_SECURITY_STRENGTH_BITS;
+	/* Cap entropy to buffer size in bits */
+	ent_bits = min_t(u32, ent_bits, outbuflen<<3);
+	pr_debug("obtained %u bits of entropy from Jitter RNG noise source\n",
+		 ent_bits);
+
+	return ent_bits;
+}
+
+u32 lrng_jent_entropylevel(void)
+{
+	return min_t(u32, jitterrng, LRNG_DRNG_SECURITY_STRENGTH_BITS);
+}
-- 
2.23.0





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v26 10/12] LRNG - add TRNG support
  2019-11-23 20:08   ` [PATCH v26 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                       ` (8 preceding siblings ...)
  2019-11-23 20:34     ` [PATCH v26 09/12] LRNG - add Jitter RNG fast noise source Stephan Müller
@ 2019-11-23 20:34     ` Stephan Müller
  2019-11-23 20:34     ` [PATCH v26 11/12] LRNG - add SP800-90B compliant health tests Stephan Müller
                       ` (2 subsequent siblings)
  12 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-23 20:34 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap

The True Random Number Generator (TRNG) provides a random number
generator with prediction resistance (SP800-90A terminology) or an NTG.1
(AIS 31 terminology).

When enabled, it obtains random numbers from the entropy pool and
maintains the information with how much entropy it was seeded with. The
TRNG only generates as much output data as it has as entropy.

The secondary DRNGs seed from the TRNG if it is present. In addition,
the TRNG is accessible from user space using the getrandom system call
with the GRND_TRUERANDOM flag.

When getrandom(GRND_TRUERANDOM) is invoked by a process possessing
CAP_SYS_ADMIN, all available entropy in the entropy pool is used to
serve the request. If the calling process does not possess that
capability, entropy is drawn to the extent that the entropy pool
will retain at least 1024 bits of entropy. This approach prevents
unprivileged processes to deplete existing entropy preventing
privileged callers from obtaining that entropy.

Since the secondary DRNG can draw from the entropy pool down to
a minimum entropy level of 512 bits, it will be provided with
entropy while an unprivileged user stresses
getrandom(GRND_TRUERANDOM).

If the TRNG is disabled, the secondary DRNGs seed from the entropy
pool. The getrandom(GRND_TRUERANDOM) call will return -EOPNOTSUPP
in this case.

The TRNG benefits from the switchable DRNG support which implies that
data provided via /dev/random is generated by the loaded DRNG.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Kconfig     |  22 +++
 drivers/char/lrng/Makefile    |   1 +
 drivers/char/lrng/lrng_trng.c | 297 ++++++++++++++++++++++++++++++++++
 3 files changed, 320 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_trng.c

diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
index 80fc723c67d2..122d67ee110e 100644
--- a/drivers/char/lrng/Kconfig
+++ b/drivers/char/lrng/Kconfig
@@ -91,4 +91,26 @@ config LRNG_JENT
 	  time or at runtime with the lrng_base.jitterrng configuration
 	  variable.
 
+config LRNG_TRNG_SUPPORT
+	bool "Enable True Random Number Generator support"
+	default y
+	help
+	  The true random number generator (TRNG) support, also
+	  known as DRNG with prediction resistance (SP800-90A
+	  terminology) or NTG.1 (AIS 31 terminology), generates
+	  random numbers after a successful reseed with entropy.
+	  Only when new entropy is provided for a new generation
+	  request, random data is provided with an equal amount
+	  as entropy was added. The TRNG is available via
+	  /dev/random.
+
+	  If the support is not enabled, /dev/random ensures that
+	  it received sufficient initial entropy and will produce
+	  random data without requiring a constant reseed with
+	  entropy. Yet it tries to regularly reseed itself with
+	  fresh entropy.
+
+	  With the TRNG support the /dev/random device will block
+	  if insufficient entropy is available.
+
 endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index a87d800c9aae..1c72bc060bce 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -14,3 +14,4 @@ obj-$(CONFIG_LRNG_DRNG_SWITCH)	+= lrng_switch.o
 obj-$(CONFIG_LRNG_DRBG)		+= lrng_drbg.o
 obj-$(CONFIG_LRNG_KCAPI)	+= lrng_kcapi.o
 obj-$(CONFIG_LRNG_JENT)		+= lrng_jent.o
+obj-$(CONFIG_LRNG_TRNG_SUPPORT)	+= lrng_trng.o
diff --git a/drivers/char/lrng/lrng_trng.c b/drivers/char/lrng/lrng_trng.c
new file mode 100644
index 000000000000..d594d5d5bffb
--- /dev/null
+++ b/drivers/char/lrng/lrng_trng.c
@@ -0,0 +1,297 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG True Random Number Generator (TRNG) processing
+ *
+ * Copyright (C) 2016 - 2019, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/capability.h>
+#include <linux/lrng.h>
+
+#include "lrng_internal.h"
+
+/* TRNG state handle */
+struct lrng_trng {
+	void *trng;				/* TRNG handle */
+	void *hash;				/* Hash handle */
+	u32 trng_entropy_bits;			/* TRNG entropy level */
+	const struct lrng_crypto_cb *crypto_cb;	/* Crypto callbacks */
+	struct mutex lock;
+};
+
+/* TRNG for GRND_TRUERANDOM and seed source for the secondary DRNG(s) */
+static struct lrng_trng lrng_trng = {
+	.trng		= &primary_chacha20,
+	.crypto_cb	= &lrng_cc20_crypto_cb,
+	.lock		= __MUTEX_INITIALIZER(lrng_trng.lock)
+};
+
+/********************************** Helper ************************************/
+
+void lrng_trng_reset(void)
+{
+	lrng_trng.trng_entropy_bits = 0;
+	pr_debug("reset TRNG\n");
+}
+
+void lrng_trng_init(void)
+{
+	mutex_lock(&lrng_trng.lock);
+	lrng_trng_reset();
+	lrng_cc20_init_state(&primary_chacha20);
+	mutex_unlock(&lrng_trng.lock);
+}
+
+u32 lrng_trng_retain(void)
+{
+	if (capable(CAP_SYS_ADMIN))
+		return 0;
+	return LRNG_EMERG_ENTROPY_TRNG_UNPRIV;
+}
+
+/************************* Random Number Generation ***************************/
+
+/* Caller must hold lrng_trng.lock */
+static int lrng_trng_generate(u8 *outbuf, u32 outbuflen)
+{
+	struct lrng_trng *trng = &lrng_trng;
+	const struct lrng_crypto_cb *crypto_cb = trng->crypto_cb;
+	int ret;
+
+	/*
+	 * Only deliver as many bytes as the DRNG is seeded with except during
+	 * initialization to provide a first seed to the secondary DRNG.
+	 */
+	if (lrng_state_min_seeded())
+		outbuflen = min_t(u32, outbuflen, trng->trng_entropy_bits>>3);
+	else
+		outbuflen = min_t(u32, outbuflen,
+				  LRNG_MIN_SEED_ENTROPY_BITS>>3);
+	if (!outbuflen)
+		return 0;
+
+	ret = crypto_cb->lrng_drng_generate_helper_full(trng->trng, outbuf,
+							outbuflen);
+	if (ret != outbuflen) {
+		pr_warn("getting random data from TRNG failed (%d)\n",
+			ret);
+		return ret;
+	}
+
+	if (trng->trng_entropy_bits > (u32)(ret<<3))
+		trng->trng_entropy_bits -= ret<<3;
+	else
+		trng->trng_entropy_bits = 0;
+	pr_debug("obtained %d bytes of random data from TRNG\n", ret);
+	pr_debug("TRNG entropy level at %u bits\n",
+		 trng->trng_entropy_bits);
+
+	return ret;
+}
+
+/**
+ * Inject data into the TRNG with a given entropy value. The function calls
+ * the DRNG's update function. This function also generates random data if
+ * requested by caller. The caller is only returned the amount of random data
+ * that is at most equal to the amount of entropy that just seeded the DRNG.
+ *
+ * Note, this function seeds the TRNG and generates data in an atomic operation.
+ *
+ * @inbuf: buffer to inject
+ * @inbuflen: length of inbuf
+ * @entropy_bits: entropy value of the data in inbuf in bits
+ * @outbuf: buffer to fill immediately after seeding to get full entropy
+ * @outbuflen: length of outbuf
+ * @return: number of bytes written to outbuf, 0 if outbuf is not supplied,
+ *	    or < 0 in case of error
+ */
+static int lrng_trng_inject(const u8 *inbuf, u32 inbuflen, u32 entropy_bits,
+			    u8 *outbuf, u32 outbuflen)
+{
+	struct lrng_trng *trng = &lrng_trng;
+	int ret;
+
+	/* cap the maximum entropy value to the provided data length */
+	entropy_bits = min_t(u32, entropy_bits, inbuflen<<3);
+
+	mutex_lock(&trng->lock);
+	ret = trng->crypto_cb->lrng_drng_seed_helper(trng->trng, inbuf,
+						      inbuflen);
+	if (ret < 0) {
+		pr_warn("(re)seeding of TRNG failed\n");
+		goto unlock;
+	}
+	pr_debug("inject %u bytes with %u bits of entropy into TRNG\n",
+		 inbuflen, entropy_bits);
+
+	/* Adjust the fill level indicator to at most the DRNG sec strength */
+	trng->trng_entropy_bits =
+		min_t(u32, trng->trng_entropy_bits + entropy_bits,
+		      LRNG_DRNG_SECURITY_STRENGTH_BITS);
+	lrng_init_ops(trng->trng_entropy_bits);
+
+	if (outbuf && outbuflen)
+		ret = lrng_trng_generate(outbuf, outbuflen);
+
+unlock:
+	mutex_unlock(&trng->lock);
+	lrng_reader_wakeup();
+
+	return ret;
+}
+
+/**
+ * Seed the TRNG from the internal noise sources and generate random data. The
+ * seeding and the generation of random data is an atomic operation.
+ *
+ * lrng_pool_trylock() must be invoked successfully by caller.
+ */
+int lrng_trng_seed(u8 *outbuf, u32 outbuflen, u32 entropy_retain)
+{
+	struct entropy_buf entropy_buf __aligned(LRNG_KCAPI_ALIGN);
+	struct lrng_trng *trng = &lrng_trng;
+	u32 total_entropy_bits;
+	int ret = 0, retrieved = 0;
+
+	/* Get available entropy in primary DRNG */
+	if (trng->trng_entropy_bits>>3) {
+		mutex_lock(&trng->lock);
+		ret = lrng_trng_generate(outbuf, outbuflen);
+		mutex_unlock(&trng->lock);
+		if (ret > 0) {
+			retrieved += ret;
+			if (ret == outbuflen)
+				goto out;
+
+			outbuf += ret;
+			outbuflen -= ret;
+		}
+		/* Disregard error code as another generate request is below. */
+	}
+
+	mutex_lock(&trng->lock);
+	total_entropy_bits = lrng_fill_seed_buffer(trng->crypto_cb, trng->hash,
+						   &entropy_buf,
+						   entropy_retain);
+	mutex_unlock(&trng->lock);
+
+	/*
+	 * Continue even of total_entropy_bits is zero - inject uninitialized
+	 * buffer into TRNG for pure mixing in this case.
+	 */
+
+	pr_debug("reseed TRNG from internal noise sources with %u bits "
+		 "of entropy\n", total_entropy_bits);
+
+	ret = lrng_trng_inject((u8 *)&entropy_buf, sizeof(entropy_buf),
+				total_entropy_bits,
+				outbuf, outbuflen);
+
+	memzero_explicit(&entropy_buf, sizeof(entropy_buf));
+
+	if (ret > 0)
+		retrieved += ret;
+
+out:
+	/* Allow the seeding operation to be called again */
+	lrng_pool_unlock();
+
+	return (ret >= 0) ? retrieved : ret;
+}
+
+/**
+ * Obtain random data from TRNG with information theoretical entropy by
+ * triggering a reseed. The TRNG will only return as many random bytes as it
+ * was seeded with.
+ *
+ * @outbuf: buffer to store the random data in
+ * @outbuflen: length of outbuf
+ * @return: < 0 on error
+ *	    >= 0 the number of bytes that were obtained
+ */
+int lrng_trng_get(u8 *outbuf, u32 outbuflen)
+{
+	int ret;
+
+	if (!outbuf || !outbuflen)
+		return 0;
+
+	lrng_drngs_init_cc20();
+
+	if (lrng_pool_trylock())
+		return -EINPROGRESS;
+	ret = lrng_trng_seed(outbuf, outbuflen, lrng_trng_retain());
+	if (ret >= 0) {
+		pr_debug("read %d bytes of full entropy data from TRNG\n", ret);
+	} else {
+		/* This is no error, but we have not generated anything */
+		if (ret == -EINPROGRESS)
+			return 0;
+		pr_debug("reading data from TRNG failed: %d\n", ret);
+	}
+
+	return ret;
+}
+
+#ifdef CONFIG_LRNG_DRNG_SWITCH
+int lrng_trng_switch(const struct lrng_crypto_cb *cb)
+{
+	int ret;
+	u8 seed[LRNG_DRNG_SECURITY_STRENGTH_BYTES];
+	void *trng, *hash;
+
+	trng = cb->lrng_drng_alloc(LRNG_DRNG_SECURITY_STRENGTH_BYTES);
+	if (IS_ERR(trng))
+		return PTR_ERR(trng);
+
+	hash = cb->lrng_hash_alloc(seed, sizeof(seed));
+	if (IS_ERR(hash)) {
+		pr_warn("could not allocate new LRNG pool hash (%ld)\n",
+			PTR_ERR(hash));
+		cb->lrng_drng_dealloc(trng);
+		return PTR_ERR(hash);
+	}
+
+	/* Update primary DRNG */
+	mutex_lock(&lrng_trng.lock);
+	/* pull from existing DRNG to seed new DRNG */
+	ret = lrng_trng.crypto_cb->lrng_drng_generate_helper_full(
+					lrng_trng.trng, seed, sizeof(seed));
+	if (ret < 0) {
+		lrng_trng_reset();
+		pr_warn("getting random data from TRNG failed (%d)\n", ret);
+	} else {
+		/*
+		 * No change of the seed status as the old and new DRNG have
+		 * same security strength.
+		 */
+		ret = cb->lrng_drng_seed_helper(trng, seed, ret);
+		if (ret < 0) {
+			lrng_trng_reset();
+			pr_warn("seeding of new TRNG failed (%d)\n", ret);
+		} else {
+			pr_debug("seeded new TRNG instance from old TRNG "
+				 "instance\n");
+		}
+	}
+	memzero_explicit(seed, sizeof(seed));
+
+	if (!lrng_get_available())
+		lrng_trng_reset();
+	lrng_trng.crypto_cb->lrng_drng_dealloc(lrng_trng.trng);
+	lrng_trng.trng = trng;
+
+	lrng_trng.crypto_cb->lrng_hash_dealloc(lrng_trng.hash);
+	lrng_trng.hash = hash;
+
+	lrng_trng.crypto_cb = cb;
+
+	mutex_unlock(&lrng_trng.lock);
+
+	pr_info("TRNG allocated\n");
+
+	return ret;
+}
+#endif	/* CONFIG_LRNG_DRNG_SWITCH */
-- 
2.23.0





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v26 11/12] LRNG - add SP800-90B compliant health tests
  2019-11-23 20:08   ` [PATCH v26 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                       ` (9 preceding siblings ...)
  2019-11-23 20:34     ` [PATCH v26 10/12] LRNG - add TRNG support Stephan Müller
@ 2019-11-23 20:34     ` Stephan Müller
  2019-11-23 20:35     ` [PATCH v26 12/12] LRNG - add interface for gathering of raw entropy Stephan Müller
  2020-01-09  8:29     ` [PATCH v27 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
  12 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-23 20:34 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap

Implement health tests for LRNG's slow noise sources as mandated by
SP-800-90B The file contains the following health tests:

- stuck test: The stuck test calculates the first, second and third
  discrete derivative of the time stamp to be processed by the LFSR.
  Only if all three values are non-zero, the received time delta is
  considered to be non-stuck.

- SP800-90B Repetition Count Test (RCT): The LRNG uses an enhanced
  version of the RCT specified in SP800-90B section 4.4.1. Instead of
  counting identical back-to-back values, the input to the RCT is the
  counting of the stuck values during the processing of received
  interrupt events. The RCT is applied with alpha=2^-30 compliant to
  the recommendation of FIPS 140-2 IG 9.8. During the counting operation,
  the LRNG always calculates the RCT cut-off value of C. If that value
  exceeds the allowed cut-off value, the LRNG will trigger the health
  test failure discussed below. An error is logged to the kernel log
  that such RCT failure occurred. This test is only applied and
  enforced in FIPS mode, i.e. when the kernel compiled with
  CONFIG_CONFIG_FIPS is started with fips=1.

- SP800-90B Adaptive Proportion Test (APT): The LRNG implements the
  APT as defined in SP800-90B section 4.4.2. The applied significance
  level again is alpha=2^-30 compliant to the recommendation of FIPS
  140-2 IG 9.8.

The aforementioned health tests are applied to the first 1,024 time stamps
obtained from interrupt events. In case one error is identified for either
the RCT, or the APT, the collected entropy is invalidated and the
SP800-90B startup health test is restarted.

As long as the SP800-90B startup health test is not completed, all LRNG
random number output interfaces that may block will block and not generate
any data. This implies that only those potentially blocking interfaces are
defined to provide random numbers that are seeded with the interrupt noise
source being SP800-90B compliant. All other output interfaces will not be
affected by the SP800-90B startup test and thus are not considered
SP800-90B compliant.

At runtime, the SP800-90B APT and RCT are applied to each time stamp
generated for a received interrupt. When either the APT and RCT indicates
a noise source failure, the LRNG is reset to a state it has immediately
after boot:

- all entropy counters are set to zero

- the SP800-90B startup tests are re-performed which implies that
getrandom(2) would block again until new entropy was collected

To summarize, the following rules apply:

• SP800-90B compliant output interfaces

  - /dev/random

  - getrandom(2) system call

  -  get_random_bytes kernel-internal interface when being triggered by
     the callback registered with add_random_ready_callback

• SP800-90B non-compliant output interfaces

  - /dev/urandom

  - get_random_bytes kernel-internal interface called directly

  - randomize_page kernel-internal interface

  - get_random_u32 and get_random_u64 kernel-internal interfaces

  - get_random_u32_wait, get_random_u64_wait, get_random_int_wait, and
    get_random_long_wait kernel-internal interfaces

If either the RCT, or the APT health test fails irrespective whether
during initialization or runtime, the following actions occur:

  1. The entropy of the entire entropy pool is invalidated.

  2. The primary and all secondary DRNGs are reset which imply that they
     are treated as being not seeded and require a reseed during next
     invocation.

  3. The SP800-90B startup health test are initiated with all
     implications of the startup tests. That implies that from that point
     on, new events must be observed and its entropy must be inserted into
     the entropy pool before random numbers are calculated from the
     entropy pool.

Further details on the SP800-90B compliance and the availability of all
test tools required to perform all tests mandated by SP800-90B are
provided at [1].

The entire health testing code is compile-time configurable.

The patch provides a CONFIG_BROKEN configuration of the APT / RCT cutoff
values which have a high likelihood to trigger the health test failure.
The BROKEN APT cutoff is set to the exact mean of the expected value if
the time stamps are equally distributed (512 time stamps divided by 16
possible values due to using the 4 LSB of the time stamp). The BROKEN
RCT cutoff value is set to 1 which is likely to be triggered during
regular operation.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Kconfig       |  56 +++++
 drivers/char/lrng/Makefile      |   1 +
 drivers/char/lrng/lrng_health.c | 409 ++++++++++++++++++++++++++++++++
 3 files changed, 466 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_health.c

diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
index 122d67ee110e..e6ca3acc1e48 100644
--- a/drivers/char/lrng/Kconfig
+++ b/drivers/char/lrng/Kconfig
@@ -113,4 +113,60 @@ config LRNG_TRNG_SUPPORT
 	  With the TRNG support the /dev/random device will block
 	  if insufficient entropy is available.
 
+config LRNG_HEALTH_TESTS
+	bool "Enable noise source online health tests"
+	help
+	  The online health tests validate the noise source at
+	  runtime for fatal errors. These tests include SP800-90B
+	  compliant tests which are invoked if the system is booted
+	  with fips=1. In case of fatal errors during active
+	  SP800-90B tests, the issue is logged and the noise
+	  data is discarded. These tests are required for full
+	  compliance with SP800-90B.
+
+	  If unsure, say Y.
+
+config LRNG_RCT_BROKEN
+	bool "SP800-90B RCT with dangerous low cutoff value"
+	depends on LRNG_HEALTH_TESTS
+	depends on BROKEN
+	default n
+	help
+	  This option enables a dangerously low SP800-90B repetitive
+	  count test (RCT) cutoff value which makes it very likely
+	  that the RCT is triggered to raise a self test failure.
+
+	  This option is ONLY intended for developers wanting to
+	  test the effectiveness of the SP800-90B RCT health test.
+
+	  If unsure, say N.
+
+config LRNG_APT_BROKEN
+	bool "SP800-90B APT with dangerous low cutoff value"
+	depends on LRNG_HEALTH_TESTS
+	depends on BROKEN
+	default n
+	help
+	  This option enables a dangerously low SP800-90B adaptive
+	  proportion test (APT) cutoff value which makes it very
+	  likely that the RCT is triggered to raise a self test
+	  failure.
+
+	  This option is ONLY intended for developers wanting to
+	  test the effectiveness of the SP800-90B APT health test.
+
+	  If unsure, say N.
+
+# Default taken from SP800-90B sec 4.4.1 - significance level 2^-30
+config LRNG_RCT_CUTOFF
+	int
+	default 30 if !LRNG_RCT_BROKEN
+	default 1 if LRNG_RCT_BROKEN
+
+# Default taken from SP800-90B sec 4.4.2 - significance level 2^-30
+config LRNG_APT_CUTOFF
+	int
+	default 325 if !LRNG_APT_BROKEN
+	default 32 if LRNG_APT_BROKEN
+
 endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index 1c72bc060bce..0713e9c0aa6e 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -15,3 +15,4 @@ obj-$(CONFIG_LRNG_DRBG)		+= lrng_drbg.o
 obj-$(CONFIG_LRNG_KCAPI)	+= lrng_kcapi.o
 obj-$(CONFIG_LRNG_JENT)		+= lrng_jent.o
 obj-$(CONFIG_LRNG_TRNG_SUPPORT)	+= lrng_trng.o
+obj-$(CONFIG_LRNG_HEALTH_TESTS)	+= lrng_health.o
diff --git a/drivers/char/lrng/lrng_health.c b/drivers/char/lrng/lrng_health.c
new file mode 100644
index 000000000000..9ea34322e0ae
--- /dev/null
+++ b/drivers/char/lrng/lrng_health.c
@@ -0,0 +1,409 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * Linux Random Number Generator (LRNG) Health Testing
+ *
+ * Copyright (C) 2019, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/fips.h>
+#include <linux/module.h>
+
+#include "lrng_internal.h"
+
+/* Stuck Test */
+struct lrng_stuck_test {
+	u32 last_time;		/* Stuck test: time of previous IRQ */
+	u32 last_delta;		/* Stuck test: delta of previous IRQ */
+	u32 last_delta2;	/* Stuck test: 2. time derivation of prev IRQ */
+};
+
+/* Repetition Count Test */
+struct lrng_rct {
+	atomic_t rct_count;	/* Number of stuck values */
+};
+
+/* Adaptive Proportion Test */
+struct lrng_apt {
+	/* Data window size */
+#define LRNG_APT_WINDOW_SIZE	512
+	/* LSB of time stamp to process */
+#define LRNG_APT_LSB		16
+#define LRNG_APT_WORD_MASK	(LRNG_APT_LSB - 1)
+	atomic_t apt_count;		/* APT counter */
+	atomic_t apt_base;		/* APT base reference */
+
+	atomic_t apt_trigger;
+	bool apt_base_set;	/* Is APT base set? */
+};
+
+/* The health test code must operate lock-less */
+struct lrng_health {
+	struct lrng_rct rct;
+	struct lrng_apt apt;
+
+	bool health_test_enabled;
+
+	/* SP800-90B startup health tests */
+#define LRNG_SP80090B_STARTUP_SAMPLES  1024
+#define LRNG_SP80090B_STARTUP_BLOCKS   ((LRNG_SP80090B_STARTUP_SAMPLES + \
+					 LRNG_APT_WINDOW_SIZE - 1) /    \
+					LRNG_APT_WINDOW_SIZE)
+	bool sp80090b_startup_done;
+	atomic_t sp80090b_startup_blocks;
+};
+
+static struct lrng_health lrng_health = {
+	.rct.rct_count = ATOMIC_INIT(0),
+
+	.apt.apt_count = ATOMIC_INIT(0),
+	.apt.apt_base = ATOMIC_INIT(-1),
+	.apt.apt_trigger = ATOMIC_INIT(LRNG_APT_WINDOW_SIZE),
+	.apt.apt_base_set = false,
+
+	.health_test_enabled = true,
+
+	.sp80090b_startup_blocks = ATOMIC_INIT(LRNG_SP80090B_STARTUP_BLOCKS),
+	.sp80090b_startup_done = false,
+};
+
+static DEFINE_PER_CPU(struct lrng_stuck_test, lrng_stuck_test);
+
+static inline bool lrng_sp80090b_health_requested(void)
+{
+	/* Health tests are only requested in FIPS mode */
+	return fips_enabled;
+}
+
+static inline bool lrng_sp80090b_health_enabled(void)
+{
+	struct lrng_health *health = &lrng_health;
+
+	return lrng_sp80090b_health_requested() && health->health_test_enabled;
+}
+
+/***************************************************************************
+ * SP800-90B Compliance
+ *
+ * If the Linux-RNG is booted into FIPS mode, the following interfaces
+ * provide an SP800-90B compliant noise source:
+ *
+ * * /dev/random
+ * * getrandom(2)
+ * * get_random_bytes when using it in conjunction with
+ *   add_random_ready_callback
+ *
+ * All other interfaces, including /dev/urandom or get_random_bytes without
+ * the add_random_ready_callback cannot claim to use an SP800-90B compliant
+ * noise source.
+ ***************************************************************************/
+
+/**
+ * Perform SP800-90B startup testing
+ */
+static inline void lrng_sp80090b_startup(struct lrng_health *health)
+{
+	if (!health->sp80090b_startup_done &&
+	    atomic_dec_and_test(&health->sp80090b_startup_blocks)) {
+		health->sp80090b_startup_done = true;
+		pr_info("SP800-90B startup health tests completed\n");
+		lrng_init_ops(0);
+
+		/*
+		 * Force a reseed of secondary DRNGs to ensure they are
+		 * seeded with entropy that passed the SP800-90B health tests.
+		 * As the primary DRNG always will reseed before generating
+		 * random numbers, it does not need a reseed trigger.
+		 */
+		lrng_sdrng_force_reseed();
+	}
+}
+
+/**
+ * Handle failure of SP800-90B startup testing
+ */
+static inline void lrng_sp80090b_startup_failure(struct lrng_health *health)
+{
+	/* Reset of LRNG and its entropy - NOTE: we are in atomic context */
+	lrng_reset();
+
+	/*
+	 * Reset the SP800-90B startup test.
+	 *
+	 * NOTE SP800-90B section 4.3 bullet 4 does not specify what
+	 * exactly is to be done in case of failure! Thus, we do what
+	 * makes sense, i.e. restarting the health test and thus gating
+	 * the output function of /dev/random and getrandom(2).
+	 */
+	atomic_set(&health->sp80090b_startup_blocks,
+		   LRNG_SP80090B_STARTUP_BLOCKS);
+}
+
+/**
+ * Handle failure of SP800-90B runtime testing
+ */
+static inline void lrng_sp80090b_runtime_failure(struct lrng_health *health)
+{
+	lrng_sp80090b_startup_failure(health);
+	health->sp80090b_startup_done = false;
+}
+
+static inline void lrng_sp80090b_failure(struct lrng_health *health)
+{
+	if (health->sp80090b_startup_done) {
+		pr_err("SP800-90B runtime health test failure - invalidating "
+		       "all existing entropy and initiate SP800-90B startup\n");
+		lrng_sp80090b_runtime_failure(health);
+	} else {
+		pr_err("SP800-90B startup test failure - resetting\n");
+		lrng_sp80090b_startup_failure(health);
+	}
+}
+
+/**
+ * Is the SP800-90B startup testing complete?
+ *
+ * This function is called by the LRNG to determine whether to unblock
+ * a certain user interface. Therefore, only the potentially blocking
+ * user interfaces are considered SP800-90B compliant.
+ */
+bool lrng_sp80090b_startup_complete(void)
+{
+	struct lrng_health *health = &lrng_health;
+
+	return (lrng_sp80090b_health_enabled()) ? health->sp80090b_startup_done:
+						  true;
+}
+
+bool lrng_sp80090b_compliant(void)
+{
+	struct lrng_health *health = &lrng_health;
+
+	return lrng_sp80090b_health_enabled() && health->sp80090b_startup_done;
+}
+
+/***************************************************************************
+ * Adaptive Proportion Test
+ *
+ * This test complies with SP800-90B section 4.4.2.
+ ***************************************************************************/
+
+/**
+ * Reset the APT counter
+ *
+ * @health [in] Reference to health state
+ */
+static inline void lrng_apt_reset(struct lrng_health *health,
+				  unsigned int time_masked)
+{
+	struct lrng_apt *apt = &health->apt;
+
+	pr_debug("APT value %d for base %d\n",
+		 atomic_read(&apt->apt_count), atomic_read(&apt->apt_base));
+
+	/* Reset APT */
+	atomic_set(&apt->apt_count, 0);
+	atomic_set(&apt->apt_base, time_masked);
+}
+
+static inline void lrng_apt_restart(struct lrng_health *health)
+{
+	struct lrng_apt *apt = &health->apt;
+
+	atomic_set(&apt->apt_trigger, LRNG_APT_WINDOW_SIZE);
+}
+
+/**
+ * Insert a new entropy event into APT
+ *
+ * This function does is void as it does not decide about the fate of a time
+ * stamp. An APT failure can only happen at the same time of a stuck test
+ * failure. Thus, the stuck failure will already decide how the time stamp
+ * is handled.
+ *
+ * @health [in] Reference to health state
+ * @now_time [in] Time stamp to process
+ */
+static inline void lrng_apt_insert(struct lrng_health *health,
+				   unsigned int now_time)
+{
+	struct lrng_apt *apt = &health->apt;
+
+	if (!lrng_sp80090b_health_requested())
+		return;
+
+	now_time &= LRNG_APT_WORD_MASK;
+
+	/* Initialization of APT */
+	if (!apt->apt_base_set) {
+		atomic_set(&apt->apt_base, now_time);
+		apt->apt_base_set = true;
+		return;
+	}
+
+	if (now_time == (unsigned int)atomic_read(&apt->apt_base)) {
+		u32 apt_val = (u32)atomic_inc_return_relaxed(&apt->apt_count);
+
+		if (apt_val >= CONFIG_LRNG_APT_CUTOFF)
+			lrng_sp80090b_failure(health);
+	}
+
+	if (atomic_dec_and_test(&apt->apt_trigger)) {
+		lrng_apt_restart(health);
+		lrng_apt_reset(health, now_time);
+		lrng_sp80090b_startup(health);
+	}
+}
+
+/***************************************************************************
+ * Repetition Count Test
+ *
+ * The LRNG uses an enhanced version of the Repetition Count Test
+ * (RCT) specified in SP800-90B section 4.4.1. Instead of counting identical
+ * back-to-back values, the input to the RCT is the counting of the stuck
+ * values while filling the entropy pool.
+ *
+ * The RCT is applied with an alpha of 2^-30 compliant to FIPS 140-2 IG 9.8.
+ *
+ * During the counting operation, the LRNG always calculates the RCT
+ * cut-off value of C. If that value exceeds the allowed cut-off value,
+ * the LRNG will invalidate all entropy for the entropy pool which implies
+ * that no data can be extracted from the entropy pool unless new entropy
+ * is received.
+ ***************************************************************************/
+
+/**
+ * Hot code path - Insert data for Repetition Count Test
+ *
+ * @health: Reference to health information
+ * @stuck: Decision of stuck test
+ */
+static inline void lrng_rct(struct lrng_health *health, int stuck)
+{
+	struct lrng_rct *rct = &health->rct;
+
+	if (!lrng_sp80090b_health_requested())
+		return;
+
+	if (stuck) {
+		u32 rct_count = atomic_add_return_relaxed(1, &rct->rct_count);
+
+		pr_debug("RCT count: %u\n", rct_count);
+
+		/*
+		 * The cutoff value is based on the following consideration:
+		 * alpha = 2^-30 as recommended in FIPS 140-2 IG 9.8.
+		 * In addition, we imply an entropy value H of 1 bit as this
+		 * is the minimum entropy required to provide full entropy.
+		 *
+		 * Note, rct_count (which equals to value B in the
+		 * pseudo code of SP800-90B section 4.4.1) starts with zero.
+		 * Hence we need to subtract one from the cutoff value as
+		 * calculated following SP800-90B.
+		 */
+		if (rct_count >= CONFIG_LRNG_RCT_CUTOFF) {
+			atomic_set(&rct->rct_count, 0);
+
+			/*
+			 * APT must start anew as we consider all previously
+			 * recorded data to contain no entropy.
+			 */
+			lrng_apt_restart(health);
+
+			lrng_sp80090b_failure(health);
+		}
+	} else {
+		atomic_set(&rct->rct_count, 0);
+	}
+}
+
+/***************************************************************************
+ * Stuck Test
+ *
+ * Checking the:
+ *      1st derivative of the event occurrence (time delta)
+ *      2nd derivative of the event occurrence (delta of time deltas)
+ *      3rd derivative of the event occurrence (delta of delta of time deltas)
+ *
+ * All values must always be non-zero. The stuck test is only valid disabled if
+ * high-resolution time stamps are identified after initialization.
+ ***************************************************************************/
+
+static inline u32 lrng_delta(u32 prev, u32 next)
+{
+	/*
+	 * Note that this (unsigned) subtraction does yield the correct value
+	 * in the wraparound-case, i.e. when next < prev.
+	 */
+	return (next - prev);
+}
+
+/**
+ * Hot code path
+ *
+ * @health: Reference to health information
+ * @now: Event time
+ * @return: 0 event occurrence not stuck (good time stamp)
+ *	    != 0 event occurrence stuck (reject time stamp)
+ */
+static inline int lrng_irq_stuck(struct lrng_stuck_test *stuck, u32 now_time)
+{
+	u32 delta = lrng_delta(stuck->last_time, now_time);
+	u32 delta2 = lrng_delta(stuck->last_delta, delta);
+	u32 delta3 = lrng_delta(stuck->last_delta2, delta2);
+
+	stuck->last_time = now_time;
+	stuck->last_delta = delta;
+	stuck->last_delta2 = delta2;
+
+	if (!delta || !delta2 || !delta3)
+		return 1;
+
+	return 0;
+}
+
+/***************************************************************************
+ * Health test interfaces
+ ***************************************************************************/
+
+/**
+ * Disable all health tests
+ */
+void lrng_health_disable(void)
+{
+	struct lrng_health *health = &lrng_health;
+
+	health->health_test_enabled = false;
+
+	if (lrng_sp80090b_health_requested())
+		pr_warn("SP800-90B compliance requested but the Linux RNG is "
+			"NOT SP800-90B compliant\n");
+}
+
+/**
+ * Hot code path - Perform health test on time stamp received from an event
+ *
+ * @now_time Time stap
+ */
+enum lrng_health_res lrng_health_test(u32 now_time)
+{
+	struct lrng_health *health = &lrng_health;
+	struct lrng_stuck_test *stuck_test = this_cpu_ptr(&lrng_stuck_test);
+	int stuck;
+
+	if (!health->health_test_enabled)
+		return lrng_health_pass;
+
+	lrng_apt_insert(health, now_time);
+
+	stuck = lrng_irq_stuck(stuck_test, now_time);
+	lrng_rct(health, stuck);
+	if (stuck) {
+		/* SP800-90B disallows using a failing health test time stamp */
+		return lrng_sp80090b_health_requested() ?
+			lrng_health_fail_drop : lrng_health_fail_use;
+	}
+
+	return lrng_health_pass;
+}
-- 
2.23.0





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v26 12/12] LRNG - add interface for gathering of raw entropy
  2019-11-23 20:08   ` [PATCH v26 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                       ` (10 preceding siblings ...)
  2019-11-23 20:34     ` [PATCH v26 11/12] LRNG - add SP800-90B compliant health tests Stephan Müller
@ 2019-11-23 20:35     ` Stephan Müller
  2020-01-09  8:29     ` [PATCH v27 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
  12 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2019-11-23 20:35 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap

The test interface allows a privileged process to capture the raw
unconditioned noise that is collected by the LRNG for statistical
analysis. Such testing allows the analysis how much entropy
the interrupt noise source provides on a given platform.
Extracted noise data is not used to seed the LRNG. This
is a test interface and not appropriate for production systems.
Yet, the interface is considered to be sufficiently secured for
production systems.

Access to the data is given through the lrng_raw debugfs file. The
data buffer should be multiples of sizeof(u32) to fill the entire
buffer. Using the option lrng_testing.boot_test=1 the raw noise of
the first 1000 entropy events since boot can be sampled.

This test interface allows generating the data required for
analysis whether the LRNG is in compliance with SP800-90B
sections 3.1.3 and 3.1.4.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Kconfig        |  16 ++
 drivers/char/lrng/Makefile       |   1 +
 drivers/char/lrng/lrng_testing.c | 269 +++++++++++++++++++++++++++++++
 3 files changed, 286 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_testing.c

diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
index e6ca3acc1e48..9335761cb2ba 100644
--- a/drivers/char/lrng/Kconfig
+++ b/drivers/char/lrng/Kconfig
@@ -169,4 +169,20 @@ config LRNG_APT_CUTOFF
 	default 325 if !LRNG_APT_BROKEN
 	default 32 if LRNG_APT_BROKEN
 
+config LRNG_TESTING
+	bool "Enable entropy test interface to LRNG noise source"
+	depends on DEBUG_FS
+	help
+	  The test interface allows a privileged process to capture
+	  the raw unconditioned noise that is collected by the LRNG
+	  for statistical analysis. Extracted noise data is not used
+	  to seed the LRNG.
+
+	  The raw noise data can be obtained using the lrng_raw
+	  debugfs file. Using the option lrng_testing.boot_test=1
+	  the raw noise of the first 1000 entropy events since boot
+	  can be sampled.
+
+	  If unsure, say N.
+
 endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index 0713e9c0aa6e..c0b6cc4301fe 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -16,3 +16,4 @@ obj-$(CONFIG_LRNG_KCAPI)	+= lrng_kcapi.o
 obj-$(CONFIG_LRNG_JENT)		+= lrng_jent.o
 obj-$(CONFIG_LRNG_TRNG_SUPPORT)	+= lrng_trng.o
 obj-$(CONFIG_LRNG_HEALTH_TESTS)	+= lrng_health.o
+obj-$(CONFIG_LRNG_TESTING)	+= lrng_testing.o
diff --git a/drivers/char/lrng/lrng_testing.c b/drivers/char/lrng/lrng_testing.c
new file mode 100644
index 000000000000..718a24660773
--- /dev/null
+++ b/drivers/char/lrng/lrng_testing.c
@@ -0,0 +1,269 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * Linux Random Number Generator (LRNG) Raw entropy collection tool
+ *
+ * Copyright (C) 2019, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/atomic.h>
+#include <linux/bug.h>
+#include <linux/debugfs.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/sched/signal.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+#include <linux/workqueue.h>
+#include <asm/errno.h>
+
+#include "lrng_internal.h"
+
+#define LRNG_TESTING_RINGBUFFER_SIZE	1024
+#define LRNG_TESTING_RINGBUFFER_MASK	(LRNG_TESTING_RINGBUFFER_SIZE - 1)
+
+static u32 lrng_testing_rb[LRNG_TESTING_RINGBUFFER_SIZE];
+static u32 lrng_rb_reader = 0;
+static u32 lrng_rb_writer = 0;
+static atomic_t lrng_testing_enabled = ATOMIC_INIT(0);
+
+static DECLARE_WAIT_QUEUE_HEAD(lrng_raw_read_wait);
+static DEFINE_SPINLOCK(lrng_raw_lock);
+
+/*
+ * 0 ==> No boot test, gathering of runtime data allowed
+ * 1 ==> Boot test enabled and ready for collecting data, gathering runtime
+ *	 data is disabled
+ * 2 ==> Boot test completed and disabled, gathering of runtime data is
+ *	 disabled
+ */
+static u32 boot_test = 0;
+module_param(boot_test, uint, 0644);
+MODULE_PARM_DESC(boot_test, "Enable gathering boot time entropy of the first"
+			    " entropy events");
+
+static inline void lrng_raw_entropy_reset(void)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&lrng_raw_lock, flags);
+	lrng_rb_reader = 0;
+	lrng_rb_writer = 0;
+	spin_unlock_irqrestore(&lrng_raw_lock, flags);
+}
+
+static void lrng_raw_entropy_init(void)
+{
+	/*
+	 * The boot time testing implies we have a running test. If the
+	 * caller wants to clear it, he has to unset the boot_test flag
+	 * at runtime via sysfs to enable regular runtime testing
+	 */
+	if (boot_test)
+		return;
+
+	lrng_raw_entropy_reset();
+	atomic_set(&lrng_testing_enabled, 1);
+	pr_warn("Enabling raw entropy collection\n");
+}
+
+static void lrng_raw_entropy_fini(void)
+{
+	if (boot_test)
+		return;
+
+	atomic_set(&lrng_testing_enabled, 0);
+	lrng_raw_entropy_reset();
+	pr_warn("Disabling raw entropy collection\n");
+}
+
+bool lrng_raw_entropy_store(u32 value)
+{
+	unsigned long flags;
+
+	if (!atomic_read(&lrng_testing_enabled) && (boot_test != 1))
+		return false;
+
+	spin_lock_irqsave(&lrng_raw_lock, flags);
+
+	/*
+	 * Disable entropy testing for boot time testing after ring buffer
+	 * is filled.
+	 */
+	if (boot_test) {
+		if (lrng_rb_writer > LRNG_TESTING_RINGBUFFER_SIZE) {
+			boot_test = 2;
+			pr_warn_once("Boot time entropy collection test "
+				     "disabled\n");
+			spin_unlock_irqrestore(&lrng_raw_lock, flags);
+			return false;
+		}
+
+		if (lrng_rb_writer == 1)
+			pr_warn("Boot time entropy collection test enabled\n");
+	}
+
+	lrng_testing_rb[lrng_rb_writer & LRNG_TESTING_RINGBUFFER_MASK] = value;
+	lrng_rb_writer++;
+
+	spin_unlock_irqrestore(&lrng_raw_lock, flags);
+
+	if (wq_has_sleeper(&lrng_raw_read_wait))
+		wake_up_interruptible(&lrng_raw_read_wait);
+
+	return true;
+}
+
+static inline bool lrng_raw_have_data(void)
+{
+	return ((lrng_rb_writer & LRNG_TESTING_RINGBUFFER_MASK) !=
+		 (lrng_rb_reader & LRNG_TESTING_RINGBUFFER_MASK));
+}
+
+static int lrng_raw_entropy_reader(u8 *outbuf, u32 outbuflen)
+{
+	unsigned long flags;
+	int collected_data = 0;
+
+	lrng_raw_entropy_init();
+
+	while (outbuflen) {
+		spin_lock_irqsave(&lrng_raw_lock, flags);
+
+		/* We have no data or reached the writer. */
+		if (!lrng_rb_writer || (lrng_rb_writer == lrng_rb_reader)) {
+
+			spin_unlock_irqrestore(&lrng_raw_lock, flags);
+
+			/*
+			 * Now we gathered all boot data, enable regular data
+			 * collection.
+			 */
+			if (boot_test) {
+				boot_test = 0;
+				goto out;
+			}
+
+			wait_event_interruptible(lrng_raw_read_wait,
+						 lrng_raw_have_data());
+			if (signal_pending(current)) {
+				collected_data = -ERESTARTSYS;
+				goto out;
+			}
+
+			continue;
+		}
+
+		/* We copy out word-wise */
+		if (outbuflen < sizeof(u32))
+			goto out;
+
+		memcpy(outbuf, &lrng_testing_rb[lrng_rb_reader], sizeof(u32));
+		lrng_rb_reader++;
+
+		spin_unlock_irqrestore(&lrng_raw_lock, flags);
+
+		outbuf += sizeof(u32);
+		outbuflen -= sizeof(u32);
+		collected_data += sizeof(u32);
+	}
+
+out:
+	lrng_raw_entropy_fini();
+	return collected_data;
+}
+
+/**************************************************************************
+ * Debugfs interface
+ **************************************************************************/
+static int lrng_raw_extract_user(char __user *buf, size_t nbytes)
+{
+	u8 *tmp, *tmp_aligned;
+	int ret = 0, large_request = (nbytes > 256);
+
+	/*
+	 * The intention of this interface is for collecting at least
+	 * 1000 samples due to the SP800-90B requirements. So, we make no
+	 * effort in avoiding allocating more memory that actually needed
+	 * by the user. Hence, we allocate sufficient memory to always hold
+	 * that amount of data.
+	 */
+	tmp = kmalloc(LRNG_TESTING_RINGBUFFER_SIZE + sizeof(u32), GFP_KERNEL);
+	if (!tmp)
+		return -ENOMEM;
+
+	tmp_aligned = PTR_ALIGN(tmp, sizeof(u32));
+
+	while (nbytes) {
+		int i;
+
+		if (large_request && need_resched()) {
+			if (signal_pending(current)) {
+				if (ret == 0)
+					ret = -ERESTARTSYS;
+				break;
+			}
+			schedule();
+		}
+
+		i = min_t(int, nbytes, LRNG_TESTING_RINGBUFFER_SIZE);
+		i = lrng_raw_entropy_reader(tmp_aligned, i);
+		if (i <= 0) {
+			if (i < 0)
+				ret = i;
+			break;
+		}
+		if (copy_to_user(buf, tmp_aligned, i)) {
+			ret = -EFAULT;
+			break;
+		}
+
+		nbytes -= i;
+		buf += i;
+		ret += i;
+	}
+
+	kzfree(tmp);
+	return ret;
+}
+
+/* DebugFS operations and definition of the debugfs files */
+static ssize_t lrng_raw_read(struct file *file, char __user *to,
+			     size_t count, loff_t *ppos)
+{
+	loff_t pos = *ppos;
+	int ret;
+
+	if (!count)
+		return 0;
+
+	ret = lrng_raw_extract_user(to, count);
+	if (ret < 0)
+		return ret;
+
+	count -= ret;
+	*ppos = pos + count;
+
+	return ret;
+}
+
+static struct file_operations lrng_raw_name_fops = {
+	.owner = THIS_MODULE,
+	.read = lrng_raw_read,
+};
+
+static int __init lrng_raw_init(void)
+{
+	struct dentry *lrng_raw_debugfs_root;
+
+	lrng_raw_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL);
+	debugfs_create_file_unsafe("lrng_raw", 0400, lrng_raw_debugfs_root,
+				   NULL, &lrng_raw_name_fops);
+
+	return 0;
+}
+
+module_init(lrng_raw_init);
-- 
2.23.0





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* Re: [PATCH v24 01/12] Linux Random Number Generator
  2019-11-11 18:18 ` [PATCH v24 01/12] Linux Random Number Generator Stephan Müller
                     ` (2 preceding siblings ...)
  2019-11-13  0:14   ` kbuild test robot
@ 2019-11-24  4:51   ` Sandy Harris
  2019-11-24  9:02     ` Stephan Mueller
  3 siblings, 1 reply; 162+ messages in thread
From: Sandy Harris @ 2019-11-24  4:51 UTC (permalink / raw)
  To: Stephan Müller
  Cc: Arnd Bergmann, Greg Kroah-Hartman, Linux Crypto Mailing List,
	LKML, linux-api, Eric W. Biederman, Alexander E. Patrakov,
	Ahmed S. Darwish, Theodore Y. Ts'o, Willy Tarreau,
	Matthew Garrett, Vito Caputo, Andreas Dilger, Jan Kara,
	Ray Strode, William Jon McCann, zhangjs, Andy Lutomirski,
	Florian Weimer, Lennart Poettering, Nicolai Stange, Peter,
	Matthias, Marcelo Henrique Cerri, Roman Drahtmueller,
	Neil Horman

Stephan Müller <smueller@chronox.de> 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 LRNG allows the TRNG and secondary DRNG mechanism to be changed
> at runtime.

Why? This strikes me as pointless complication.

> * 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.

^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v24 01/12] Linux Random Number Generator
  2019-11-24  4:51   ` Sandy Harris
@ 2019-11-24  9:02     ` Stephan Mueller
  0 siblings, 0 replies; 162+ messages in thread
From: Stephan Mueller @ 2019-11-24  9:02 UTC (permalink / raw)
  To: Sandy Harris
  Cc: Arnd Bergmann, Greg Kroah-Hartman, Linux Crypto Mailing List,
	LKML, linux-api, Eric W. Biederman, Alexander E. Patrakov,
	Ahmed S. Darwish, Theodore Y. Ts'o, Willy Tarreau,
	Matthew Garrett, Vito Caputo, Andreas Dilger, Jan Kara,
	Ray Strode, William Jon McCann, zhangjs, Andy Lutomirski,
	Florian Weimer, Lennart Poettering, Nicolai Stange, Peter,
	Matthias, Marcelo Henrique Cerri, Roman Drahtmueller,
	Neil Horman

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

Hi Sandy,

> Stephan Müller <smueller@chronox.de> 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



^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v26 01/12] Linux Random Number Generator
  2019-11-23 20:10     ` [PATCH v26 01/12] Linux Random Number Generator Stephan Müller
@ 2019-11-24 22:44       ` kbuild test robot
  2019-11-25  6:29         ` Stephan Mueller
  0 siblings, 1 reply; 162+ messages in thread
From: kbuild test robot @ 2019-11-24 22:44 UTC (permalink / raw)
  To: Stephan Müller
  Cc: kbuild-all, Arnd Bergmann, Greg Kroah-Hartman, linux-crypto,
	LKML, linux-api, Eric W. Biederman, Alexander E. Patrakov,
	Ahmed S. Darwish, Theodore Y. Ts'o, Willy Tarreau,
	Matthew Garrett, Vito Caputo, Andreas Dilger, Jan Kara,
	Ray Strode, William Jon McCann, zhangjs, Andy Lutomirski,
	Florian Weimer, Lennart Poettering, Nicolai Stange, Peter,
	Matthias, Marcelo Henrique Cerri, Roman Drahtmueller,
	Neil Horman, Randy Dunlap

[-- Attachment #1: Type: text/plain, Size: 2717 bytes --]

Hi "Stephan,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on char-misc/char-misc-testing]
[also build test ERROR on v5.4-rc8 next-20191122]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]

url:    https://github.com/0day-ci/linux/commits/Stephan-M-ller/dev-random-a-new-approach-with-full-SP800-90B/20191125-042152
base:   https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git b78cda795ac83333293f1bfa3165572a47e550c2
config: sh-allmodconfig (attached as .config)
compiler: sh4-linux-gcc (GCC) 7.4.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        GCC_VERSION=7.4.0 make.cross ARCH=sh 

If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@intel.com>

All error/warnings (new ones prefixed by >>):

   In file included from include/linux/printk.h:6:0,
                    from include/linux/kernel.h:15,
                    from include/asm-generic/bug.h:19,
                    from arch/sh/include/asm/bug.h:112,
                    from include/linux/bug.h:5,
                    from include/linux/mmdebug.h:5,
                    from include/linux/percpu.h:5,
                    from include/asm-generic/irq_regs.h:11,
                    from ./arch/sh/include/generated/asm/irq_regs.h:1,
                    from drivers/char/lrng/lrng_pool.c:10:
>> drivers/char/lrng/lrng_pool.c:216:15: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
    core_initcall(lrng_init_time_source);
                  ^
   include/linux/init.h:197:50: note: in definition of macro '___define_initcall'
      __attribute__((__section__(#__sec ".init"))) = fn;
                                                     ^~
   include/linux/init.h:218:28: note: in expansion of macro '__define_initcall'
    #define core_initcall(fn)  __define_initcall(fn, 1)
                               ^~~~~~~~~~~~~~~~~
>> drivers/char/lrng/lrng_pool.c:216:1: note: in expansion of macro 'core_initcall'
    core_initcall(lrng_init_time_source);
    ^~~~~~~~~~~~~
   cc1: some warnings being treated as errors

vim +216 drivers/char/lrng/lrng_pool.c

   215	
 > 216	core_initcall(lrng_init_time_source);
   217	

---
0-DAY kernel test infrastructure                 Open Source Technology Center
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 52266 bytes --]

^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v26 01/12] Linux Random Number Generator
  2019-11-24 22:44       ` kbuild test robot
@ 2019-11-25  6:29         ` Stephan Mueller
  0 siblings, 0 replies; 162+ messages in thread
From: Stephan Mueller @ 2019-11-25  6:29 UTC (permalink / raw)
  To: kbuild test robot
  Cc: kbuild-all, Arnd Bergmann, Greg Kroah-Hartman, linux-crypto,
	LKML, linux-api, Eric W. Biederman, Alexander E. Patrakov,
	Ahmed S. Darwish, Theodore Y. Ts'o, Willy Tarreau,
	Matthew Garrett, Vito Caputo, Andreas Dilger, Jan Kara,
	Ray Strode, William Jon McCann, zhangjs, Andy Lutomirski,
	Florian Weimer, Lennart Poettering, Nicolai Stange, Peter,
	Matthias, Marcelo Henrique Cerri, Roman Drahtmueller,
	Neil Horman, Randy Dunlap

Am Sonntag, 24. November 2019, 23:44:13 CET schrieb kbuild test robot:

Hi kbuild,

> Hi "Stephan,
> 
> Thank you for the patch! Yet something to improve:
> 
> [auto build test ERROR on char-misc/char-misc-testing]
> [also build test ERROR on v5.4-rc8 next-20191122]
> [if your patch is applied to the wrong git tree, please drop us a note to
> help improve the system. BTW, we also suggest to use '--base' option to
> specify the base tree in git format-patch, please see
> https://stackoverflow.com/a/37406982]
> 
> url:   
> https://github.com/0day-ci/linux/commits/Stephan-M-ller/dev-random-a-new-ap
> proach-with-full-SP800-90B/20191125-042152 base:  
> https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git
> b78cda795ac83333293f1bfa3165572a47e550c2 config: sh-allmodconfig (attached
> as .config)
> compiler: sh4-linux-gcc (GCC) 7.4.0
> reproduce:
>         wget
> https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O
> ~/bin/make.cross chmod +x ~/bin/make.cross
>         # save the attached .config to linux build tree
>         GCC_VERSION=7.4.0 make.cross ARCH=sh
> 
> If you fix the issue, kindly add following tag
> Reported-by: kbuild test robot <lkp@intel.com>
> 
> All error/warnings (new ones prefixed by >>):
> 
>    In file included from include/linux/printk.h:6:0,
>                     from include/linux/kernel.h:15,
>                     from include/asm-generic/bug.h:19,
>                     from arch/sh/include/asm/bug.h:112,
>                     from include/linux/bug.h:5,
>                     from include/linux/mmdebug.h:5,
>                     from include/linux/percpu.h:5,
>                     from include/asm-generic/irq_regs.h:11,
>                     from ./arch/sh/include/generated/asm/irq_regs.h:1,
> 
>                     from drivers/char/lrng/lrng_pool.c:10:
> >> drivers/char/lrng/lrng_pool.c:216:15: error: initialization from
> >> incompatible pointer type [-Werror=incompatible-pointer-types]

The function prototype needs to return an int - I wonder why that did not show 
in my x86 compile run.

It will be fixed in the next set.

>     core_initcall(lrng_init_time_source);
>                   ^
>    include/linux/init.h:197:50: note: in definition of macro
> '___define_initcall' __attribute__((__section__(#__sec ".init"))) = fn;
>                                                      ^~
>    include/linux/init.h:218:28: note: in expansion of macro
> '__define_initcall' #define core_initcall(fn)  __define_initcall(fn, 1)
>                                ^~~~~~~~~~~~~~~~~
> 
> >> drivers/char/lrng/lrng_pool.c:216:1: note: in expansion of macro
> >> 'core_initcall'
>     core_initcall(lrng_init_time_source);
>     ^~~~~~~~~~~~~
>    cc1: some warnings being treated as errors
> 
> vim +216 drivers/char/lrng/lrng_pool.c
> 
>    215
> 
>  > 216	core_initcall(lrng_init_time_source);
> 
>    217
> 
> ---
> 0-DAY kernel test infrastructure                 Open Source Technology
> Center https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org Intel
> Corporation



Ciao
Stephan



^ permalink raw reply	[flat|nested] 162+ messages in thread

* [PATCH v27 00/12] /dev/random - a new approach with full SP800-90B
  2019-11-23 20:08   ` [PATCH v26 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                       ` (11 preceding siblings ...)
  2019-11-23 20:35     ` [PATCH v26 12/12] LRNG - add interface for gathering of raw entropy Stephan Müller
@ 2020-01-09  8:29     ` Stephan Müller
  2020-01-09  8:30       ` [PATCH v27 01/12] Linux Random Number Generator Stephan Müller
                         ` (12 more replies)
  12 siblings, 13 replies; 162+ messages in thread
From: Stephan Müller @ 2020-01-09  8:29 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap, Julia Lawall

Hi,

The following patch set provides a different approach to /dev/random which is
called Linux Random Number Generator (LRNG) to collect entropy within the Linux
kernel. The main improvements compared to the existing /dev/random is to provide
sufficient entropy during boot time as well as in virtual environments and when
using SSDs. A secondary design goal is to limit the impact of the entropy
collection on massive parallel systems and also allow the use accelerated
cryptographic primitives. Also, all steps of the entropic data processing are
testable.

The LRNG patch set allows a user to select use of the existing /dev/random or
the LRNG during compile time. As the LRNG provides API and ABI compatible
interfaces to the existing /dev/random implementation, the user can freely chose
the RNG implementation without affecting kernel or user space operations.

This patch set provides early boot-time entropy which implies that no
additional flags to the getrandom(2) system call discussed recently on
the LKML is considered to be necessary. Yet, if additional flags are
introduced to cover special hardware, the LRNG implementation will also
provide them to be fully ABI and API compliant as already discussed on
LKML.

The LRNG is fully compliant to SP800-90B requirements and is shipped with a
full SP800-90B assessment and all required test tools. The existing /dev/random
implementation on the other hand has architectural limitations which
does not easily allow to bring the implementation in compliance with
SP800-90B. The key statement that causes concern is SP800-90B section
3.1.6. This section denies crediting entropy to multiple similar noise
sources. This section explicitly references different noise sources resting
on the timing of events and their derivatives (i.e. it is a direct complaint
to the existing existing /dev/random implementation). Therefore, SP800-90B
now denies the very issue mentioned in [1] with the existing /dev/random
implementation for a long time: crediting entropy to interrupts as well as
crediting entropy to derivatives of interrupts (HID and disk events). This is
not permissible with SP800-90B.

SP800-90B specifies various requirements for the noise source(s) that seed any
DRNG including SP800-90A DRBGs. In about a year from now, SP800-90B will be
mandated for all noise sources that provide entropy to DRBGs as part of a FIPS
140-[2|3] validation or other evaluation types. That means, if we there are no
solutions to comply with the requirements of SP800-90B found till one year
from now, any random number generation and ciphers based on random numbers
on Linux will be considered and treated as not applicable and delivering
no entropy! As /dev/urandom, getrandom(2) and /dev/random are the most
common and prevalent noise sources for DRNGs, all these DRNGs are affected.
This applies across the board for all validations of cryptography executing on
Linux (kernel and user space modules).

For users that are not interested in SP800-90B, the entire code for the
compliance as well as test interfaces can be deselected at compile time.

The design and implementation is driven by a set of goals described in [1]
that the LRNG completely implements. Furthermore, [1] includes the full
assessment of the SP800-90B compliance as well as a comparison with RNG
design suggestions of SP800-90C, and AIS20/31.

The LRNG provides a complete separation of the noise source maintenance
and the collection of entropy into an entropy pool from the post-processing
using a pseudo-random number generator. Different DRNGs are supported,
including:

* The LRNG can be compile-time enabled to replace the existing /dev/random
  implementation. When not selecting the LRNG at compile time (default), the
  existing /dev/random implementation is built.

* Built-in ChaCha20 DRNG which has no dependency to other kernel
  frameworks.

* SP800-90A DRBG using the kernel crypto API including its accelerated
  raw cipher implementations. This implies that the output of /dev/random,
  getrandom(2), /dev/urandom or get_random_bytes is fully compliant to
  SP800-90A.

* Arbitrary DRNGs registered with the kernel crypto API

* Full compliance with SP800-90B which covers the startup and runtime health
  tests mandated by SP800-90B as well as providing the test tools and test
  interfaces to obtain raw noise data securely. The test tools are provided at
  [1].

Booting the patch with the kernel command line option
"dyndbg=file drivers/char/lrng/* +p" generates logs indicating the operation
of the LRNG. Each log is pre-pended with "lrng".

The LRNG has a flexible design by allowing an easy replacement of the
deterministic random number generator component.

Compared to the existing /dev/random implementation, the compiled binary
is smaller when the LRNG is compiled with all options equal to the
existing /dev/random (i.e. only CONFIG_LRNG is set): random.o is 52.5 kBytes
whereas all LRNG object files are in 49 kBytes in size. The fully
SP800-90A/SP800-90B compliant binary code (CONFIG_LRNG,
CONFIG_LRNG_DRNG_SWITCH, CONFIG_LRNG_DRBG, CONFIG_LRNG_HEALTH_TESTS)
uses some 61 kBytes. In addition, the LRNG is about 50% faster in the
performance critical interrupt handler code path compared to the existing
/dev/random implementation.

[1] http://www.chronox.de/lrng.html - If the patch is accepted, I would
be volunteering to convert the documentation into RST format and
contribute it to the Linux kernel documentation directory.

Changes (compared to the previous patch set):

* fix function prototype of lrng_init_time_source

* fix indentation in getrandom

* add unlock to error code path as reported by Julia Lawall

* integrate 0da522107e5d9c000a4871d52e570912aa1225a2 from Arnd Bergmann and
  supplemental patch 4aa37c463764052c68c5c430af2a67b5d784c1e0 from
  Jason A. Donenfeld

* use new jitterentropy.h header file

* add power-on self-tests of security critical functions of hash_df, LFSR,
  ChaCha20 DRNG, and time stamp array management

* add support for significantly reduced runtime memory footprint as outlined
  in patch 1

* drop TRNG support - the LRNG has the same user experience as random.c
  with Andy Lutomirski's recent patch removing the blocking_pool - rename
  all *sdrng* symbols to *drng*

* ensure that external noise sources can provide seed at least once when a
  DRNG is reseeded to ensure internal and external noise sources are balanced

* add full documentation to all API calls provided to the remainder of the
  kernel

* ensure that after a SP800-90B health test failure the interrupt handler
  triggers reseeds like during boot time

This patch requires the presence of patch
75551dbf112c992bc6c99a972990b3f272247e23 from Ted Tso's kernel tree
(specifically the addition of GRND_INSECURE to random.h)

As a side node: With the switchable DRNG support offered in this patch set,
the following areas could be removed. As the existing /dev/random has no support
for switchable DRNGs, however, this is not yet feasible though.

* remove lrng_ready_list and all code around it in lrng_interfaces.c

* remove the kernel crypto API RNG API to avoid having two random number
  providing APIs - this would imply that all RNGs developed for this API would
  be converted to the LRNG interface

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>

Stephan Mueller (12):
  Linux Random Number Generator
  LRNG - allocate one DRNG instance per NUMA node
  LRNG - sysctls and /proc interface
  LRNG - add switchable DRNG support
  crypto: DRBG - externalize DRBG functions for LRNG
  LRNG - add SP800-90A DRBG extension
  LRNG - add kernel crypto API PRNG extension
  crypto: provide access to a static Jitter RNG state
  LRNG - add Jitter RNG fast noise source
  LRNG - add SP800-90B compliant health tests
  LRNG - add interface for gathering of raw entropy
  LRNG - add power-on and runtime self-tests

 MAINTAINERS                                   |   7 +
 crypto/drbg.c                                 |  16 +-
 crypto/jitterentropy-kcapi.c                  |   3 +-
 crypto/jitterentropy.c                        |  25 +-
 drivers/char/Kconfig                          |   2 +
 drivers/char/Makefile                         |   9 +-
 drivers/char/lrng/Kconfig                     | 203 ++++++
 drivers/char/lrng/Makefile                    |  19 +
 drivers/char/lrng/lrng_archrandom.c           |  92 +++
 drivers/char/lrng/lrng_aux.c                  | 148 +++++
 drivers/char/lrng/lrng_chacha20.c             | 317 +++++++++
 drivers/char/lrng/lrng_chacha20.h             |  25 +
 drivers/char/lrng/lrng_drbg.c                 | 261 ++++++++
 drivers/char/lrng/lrng_drng.c                 | 397 +++++++++++
 drivers/char/lrng/lrng_health.c               | 409 ++++++++++++
 drivers/char/lrng/lrng_interfaces.c           | 622 ++++++++++++++++++
 drivers/char/lrng/lrng_internal.h             | 305 +++++++++
 drivers/char/lrng/lrng_jent.c                 |  87 +++
 drivers/char/lrng/lrng_kcapi.c                | 328 +++++++++
 drivers/char/lrng/lrng_lfsr.h                 | 152 +++++
 drivers/char/lrng/lrng_numa.c                 | 101 +++
 drivers/char/lrng/lrng_pool.c                 | 585 ++++++++++++++++
 drivers/char/lrng/lrng_proc.c                 | 163 +++++
 drivers/char/lrng/lrng_selftest.c             | 418 ++++++++++++
 drivers/char/lrng/lrng_sw_noise.c             | 102 +++
 drivers/char/lrng/lrng_sw_noise.h             |  57 ++
 drivers/char/lrng/lrng_switch.c               | 179 +++++
 drivers/char/lrng/lrng_testing.c              | 271 ++++++++
 include/crypto/drbg.h                         |   7 +
 .../crypto/internal}/jitterentropy.h          |   3 +
 include/linux/lrng.h                          |  71 ++
 31 files changed, 5374 insertions(+), 10 deletions(-)
 create mode 100644 drivers/char/lrng/Kconfig
 create mode 100644 drivers/char/lrng/Makefile
 create mode 100644 drivers/char/lrng/lrng_archrandom.c
 create mode 100644 drivers/char/lrng/lrng_aux.c
 create mode 100644 drivers/char/lrng/lrng_chacha20.c
 create mode 100644 drivers/char/lrng/lrng_chacha20.h
 create mode 100644 drivers/char/lrng/lrng_drbg.c
 create mode 100644 drivers/char/lrng/lrng_drng.c
 create mode 100644 drivers/char/lrng/lrng_health.c
 create mode 100644 drivers/char/lrng/lrng_interfaces.c
 create mode 100644 drivers/char/lrng/lrng_internal.h
 create mode 100644 drivers/char/lrng/lrng_jent.c
 create mode 100644 drivers/char/lrng/lrng_kcapi.c
 create mode 100644 drivers/char/lrng/lrng_lfsr.h
 create mode 100644 drivers/char/lrng/lrng_numa.c
 create mode 100644 drivers/char/lrng/lrng_pool.c
 create mode 100644 drivers/char/lrng/lrng_proc.c
 create mode 100644 drivers/char/lrng/lrng_selftest.c
 create mode 100644 drivers/char/lrng/lrng_sw_noise.c
 create mode 100644 drivers/char/lrng/lrng_sw_noise.h
 create mode 100644 drivers/char/lrng/lrng_switch.c
 create mode 100644 drivers/char/lrng/lrng_testing.c
 rename {crypto => include/crypto/internal}/jitterentropy.h (84%)
 create mode 100644 include/linux/lrng.h

-- 
2.24.1





^ permalink raw reply	[flat|nested] 162+ messages in thread

* [PATCH v27 01/12] Linux Random Number Generator
  2020-01-09  8:29     ` [PATCH v27 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
@ 2020-01-09  8:30       ` Stephan Müller
  2020-01-16  6:09         ` kbuild test robot
  2020-01-09  8:31       ` [PATCH v27 02/12] LRNG - allocate one DRNG instance per NUMA node Stephan Müller
                         ` (11 subsequent siblings)
  12 siblings, 1 reply; 162+ messages in thread
From: Stephan Müller @ 2020-01-09  8:30 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap, Julia Lawall

In an effort to provide a flexible implementation for a random number
generator that also delivers entropy during early boot time, allows
replacement of the deterministic random number generation mechanism,
implement the various components in separate code for easier
maintenance, and provide compliance to SP800-90[A|B|C], introduce
the Linux Random Number Generator (LRNG) framework.

The general design is as follows. Additional implementation details
are given in [1]. The LRNG consists of the following components:

1. The LRNG implements a DRNG. The DRNG always generates the
requested amount of output. When using the SP800-90A terminology
it operates without prediction resistance. The secondary DRNG
maintains a counter of how many bytes were generated since last
re-seed and a timer of the elapsed time since last re-seed. If either
the counter or the timer reaches a threshold, the secondary DRNG is
seeded from the entropy pool.

In case the Linux kernel detects a NUMA system, one secondary DRNG
instance per NUMA node is maintained.

2. The DRNG is seeded by concatenating the data from the
following sources:

(a) the output of the entropy pool,

(b) the Jitter RNG if available and enabled, and

(c) the CPU-based noise source such as Intel RDRAND if available and
enabled.

The entropy estimate of the data of all noise sources are added to
form the entropy estimate of the data used to seed the DRNG with.
The LRNG ensures, however, that the DRNG after seeding is at
maximum the security strength of the DRNG.

The LRNG is designed such that none of these noise sources can dominate
the other noise sources to provide seed data to the DRNG during due to
the following:

(a) During boot time, the amount of received interrupts are the trigger
points to (re)seed the DRNG.

(b) At runtime, the available entropy from the slow noise source is
concatenated with a pre-defined amount of data from the fast noise
sources. In addition, each DRNG reseed operation triggers external
noise source providers to deliver one block of data.

3. The entropy pool accumulates entropy obtained from certain events,
which will henceforth be collectively called "slow noise sources".
The entropy pool collects noise data from slow noise sources. Any data
received by the LRNG from the slow noise sources is inserted into the
entropy pool using an LFSR with a primitive and irreducible polynomial.
The following sources of entropy are used:

 (a) When an interrupt occurs, the high-resolution time stamp is mixed
into the LFSR. This time stamp is credited with heuristically implied
entropy.

 (b) HID event data like the key stroke or the mouse coordinates are
mixed into the LFSR. This data is not credited with entropy by the LRNG.

 (c) Device drivers may provide data that is mixed into the LFSR. This
data is not credited with entropy by the LRNG.

 (d) After the entropy pool is ``read'' by the DRNG, the data
used to seed the DRNG is mixed back into the entropy pool to
stir the pool. This data is not credited with entropy by the LRNG.

Any data provided from user space by either writing to /dev/random,
/dev/urandom or the IOCTL of RNDADDENTROPY on both device files
are always injected into the entropy pool.

In addition, when a hardware random number generator covered by the
Linux kernel HW generator framework wants to deliver random numbers,
it is injected into the entropy pool as well. HW generator noise source
is handled separately from the other noise source due to the fact that
the HW generator framework may decide by itself when to deliver data
whereas the other noise sources always requested for data driven by the
LRNG operation. Similarly any user space provided data is inserted into
the entropy pool.

When the DRNG requires data from the entropy pool, the entire
entropy pool is processed with an SP800-90A section 10.3.1 compliant
hash_df function to generate random numbers.

To speed up the interrupt handling code of the LRNG, the time stamp
collected for an interrupt event is truncated to the 8 least
significant bits. 64 truncated time stamps are concatenated and then
jointly inserted into the LFSR. During boot time, until the fully seeded
stage is reached, each time stamp with its 32 least significant bits is
inserted into the LFSR at the time of arrival.

The LRNG allows the DRNG mechanism to be changed at runtime. Per default,
a ChaCha20-based DRNG is used. The ChaCha20-DRNG implemented for the
LRNG is also provided as a stand-alone user space deterministic random
number generator. The LRNG also offers an SP800-90A DRBG based on the
Linux kernel crypto API DRBG implementation.

The processing of entropic data from the noise source before injecting
them into the DRNG is performed with the following mathematical
operations:

1. LFSR: The 8 least significant bits of the time stamp data received
from the interrupts are processed with an LFSR. That LFSR is implemented
identically to the LSFR used in the existing /dev/random implementation
except that it is capable of processing an entire word and that a
different polynomial is used. The reason for the different polynomial
is performance in a performance sensitive code section, the interrupt
handler. The chosen polynomials have 4 taps. Also, this LFSR-approach
is used in the OpenBSD /dev/random equivalent.

2. Concatenation: The temporary seed buffer used to seed the DRNG is
a concatenation of parts of the entropy pool data, and the CPU noise
source output.

The DRNG always tries to seed itself with 256 bits of entropy, except
during boot. In any case, if the noise sources cannot deliver that
amount, the available entropy is used and the DRNG keeps track on how
much entropy it was seeded with. The entropy implied by the LRNG
available in the entropy pool may be too conservative. To ensure
that during boot time all available entropy from the entropy pool is
transferred to the DRNG, the hash_df function always generates 256
data bits during boot to seed the DRNG. During boot, the DRNG is
seeded as follows:

1. The DRNG is reseeded from the entropy pool and potentially the fast
noise sources if the entropy pool has collected at least 32 bits of
entropy from the interrupt noise source. The goal of this step is to
ensure that the DRNG receives some initial entropy as early as
possible. In addition it receives the entropy available from
the fast noise sources.

2. The DRNG is reseeded from the entropy pool and potentially the fast
noise sources if all noise sources collectively can provide at least
128 bits of entropy.

3. The DRNG is reseeded from the entropy pool and potentially the fast
noise sources if all noise sources collectivel can provide at least 256
bits.

At the time of the reseeding steps, the DRNG requests as much entropy as
is available in order to skip certain steps and reach the seeding level
of 256 bits. This may imply that one or more of the aforementioned steps
are skipped.

In all listed steps, the DRNG is (re)seeded with a number of random
bytes from the entropy pool that is at most the amount of entropy
present in the entropy pool. This means that when the entropy pool
contains 128 or 256 bits of entropy, the DRNG is seeded with that
amount of entropy as well.

Before the DRNG is seeded with 256 bits of entropy in step 3,
requests of random data from /dev/random are not processed.

The hash_df operation providing random data from the entropy pool will
always require that all entropy sources collectively can deliver at
least 129 entropy bits as configured with (128 bits of entropy for
seeding plus one bit of entropy that is lost with the post
processing as defined in SP800-90B).

The DRNG operates as deterministic random number generator with the
following properties:

* The maximum number of random bytes that can be generated with one
DRNG generate operation is limited to 4096 bytes. When longer random
numbers are requested, multiple DRNG generate operations are performed.
The ChaCha20 DRNG as well as the SP800-90A DRBGs implement an update of
their state after completing a generate request for backtracking
resistance.

* The secondary DRNG is reseeded with whatever entropy is available –
in the worst case where no additional entropy can be provided by the
noise sources, the DRNG is not re-seeded and continues its operation
to try to reseed again after again the expiry of one of these thresholds:

 - If the last reseeding of the secondary DRNG is more than 600 seconds
   ago, or

 - 2^20 DRNG generate operations are performed, whatever comes first, or

 - the secondary DRNG is forced to reseed before the next generation of
   random numbers if data has been injected into the LRNG by writing data
   into /dev/random or /dev/urandom.

The chosen values prevent high-volume requests from user space to cause
frequent reseeding operations which drag down the performance of the
DRNG.

With the automatic reseeding after 600 seconds, the LRNG is triggered
to reseed itself before the first request after a suspend that put the
hardware to sleep for longer than 600 seconds.

The LRNG uses the following runtime memory using the currently
smallest configuration:

* 572 bytes (512 bytes for the entropy pool and 64 for the entropy pool
  meta data) for the entropy pool management

* 64 bytes per CPU for the time stamp array

To support smaller devices including IoT environments, this patch
allows reducing the runtime memory footprint of the LRNG at compile
time by selecting smaller entropy pool sizes.

The entropy pool has support for sizes of 256, 128 and 64 bytes supported
by primitive and irreducible polynomials.

The time stamp array is reduced to one atomic_t variable per CPU, i.e.
4 bytes when CONFIG_BASE_SMALL is selected during kernel
configuration. This implies that after the receipt of 4 interrupts on
one CPU, the data is injected into the LFSR. Depending on the behavior
of the CPU caches, this may imply that the average interrupt handler
execution time increases a bit, since instead of injecting 8 atomic_t
values at one given time into the LFSR, only one is processed which
may incur cache misses.

When selecting the compilation of a kernel for a small environment,
prevent the allocation of a buffer up to 4096 bytes to serve user space
requests. In this case, the stack variable of 64 bytes is used to serve
all user space requests.

The LRNG has the following properties:

* internal noise source: interrupts timing with fast boot time seeding

* 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().

* lockless LFSR to collect raw entropy supporing concurrency-free
  use of massive parallel systems

* use of standalone ChaCha20 based RNG with the option to use a
  different DRNG selectable at compile time

* "atomic" seeding of secondary DRBG to ensure full entropy transport

* instantiate one DRNG per NUMA node

* support for runtime switchable output DRNGs

* use of only well-defined entropy-preserving operations to collect,
compress and forward entropy: concatenation, LFSR, SP800-90A hash_df
function

* compile-time selectable entropy pool size: the choice also
uses the applicable LFSR polynomial to maintain the entropy pool
size

* support of small systems by allowing the reduction of the
runtime memory needs

Further details including the rationale for the design choices and
properties of the LRNG together with testing is provided at [1].
In addition, the documentation explains the conducted regression
tests to verify that the LRNG is API and ABI compatible with the
existing /dev/random implementation.

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

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Mathematical aspects Reviewed-by: "Peter, Matthias" <matthias.peter@bsi.bund.de>
Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 MAINTAINERS                         |   7 +
 drivers/char/Kconfig                |   2 +
 drivers/char/Makefile               |   9 +-
 drivers/char/lrng/Kconfig           |  67 +++
 drivers/char/lrng/Makefile          |   9 +
 drivers/char/lrng/lrng_archrandom.c |  92 ++++
 drivers/char/lrng/lrng_aux.c        | 148 +++++++
 drivers/char/lrng/lrng_chacha20.c   | 317 ++++++++++++++
 drivers/char/lrng/lrng_chacha20.h   |  25 ++
 drivers/char/lrng/lrng_drng.c       | 397 ++++++++++++++++++
 drivers/char/lrng/lrng_interfaces.c | 623 ++++++++++++++++++++++++++++
 drivers/char/lrng/lrng_internal.h   | 296 +++++++++++++
 drivers/char/lrng/lrng_lfsr.h       | 152 +++++++
 drivers/char/lrng/lrng_pool.c       | 585 ++++++++++++++++++++++++++
 drivers/char/lrng/lrng_sw_noise.c   | 102 +++++
 drivers/char/lrng/lrng_sw_noise.h   |  57 +++
 include/linux/lrng.h                |  71 ++++
 17 files changed, 2958 insertions(+), 1 deletion(-)
 create mode 100644 drivers/char/lrng/Kconfig
 create mode 100644 drivers/char/lrng/Makefile
 create mode 100644 drivers/char/lrng/lrng_archrandom.c
 create mode 100644 drivers/char/lrng/lrng_aux.c
 create mode 100644 drivers/char/lrng/lrng_chacha20.c
 create mode 100644 drivers/char/lrng/lrng_chacha20.h
 create mode 100644 drivers/char/lrng/lrng_drng.c
 create mode 100644 drivers/char/lrng/lrng_interfaces.c
 create mode 100644 drivers/char/lrng/lrng_internal.h
 create mode 100644 drivers/char/lrng/lrng_lfsr.h
 create mode 100644 drivers/char/lrng/lrng_pool.c
 create mode 100644 drivers/char/lrng/lrng_sw_noise.c
 create mode 100644 drivers/char/lrng/lrng_sw_noise.h
 create mode 100644 include/linux/lrng.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 8982c6e013b3..f9beac15783c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9606,6 +9606,13 @@ F:	Documentation/core-api/atomic_ops.rst
 F:	Documentation/core-api/refcount-vs-atomic.rst
 F:	Documentation/memory-barriers.txt
 
+LINUX RANDOM NUMBER GENERATOR (LRNG) DRIVER
+M:	Stephan Mueller <smueller@chronox.de>
+S:	Maintained
+W:	https://www.chronox.de/lrng.html
+F:	drivers/char/lrng/*
+F:	include/linux/lrng.h
+
 LIS3LV02D ACCELEROMETER DRIVER
 M:	Eric Piel <eric.piel@tremplin-utc.net>
 S:	Maintained
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 26956c006987..1e758735f633 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -535,6 +535,8 @@ config ADI
 	  and SSM (Silicon Secured Memory).  Intended consumers of this
 	  driver include crash and makedumpfile.
 
+source "drivers/char/lrng/Kconfig"
+
 endmenu
 
 config RANDOM_TRUST_CPU
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 7c5ea6f9df14..46ede09fd6d3 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -3,7 +3,14 @@
 # Makefile for the kernel character device drivers.
 #
 
-obj-y				+= mem.o random.o
+obj-y				+= mem.o
+
+ifeq ($(CONFIG_LRNG),y)
+  obj-y				+= lrng/
+else
+  obj-y				+= random.o
+endif
+
 obj-$(CONFIG_TTY_PRINTK)	+= ttyprintk.o
 obj-y				+= misc.o
 obj-$(CONFIG_ATARI_DSP56K)	+= dsp56k.o
diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
new file mode 100644
index 000000000000..56f13efd3592
--- /dev/null
+++ b/drivers/char/lrng/Kconfig
@@ -0,0 +1,67 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Linux Random Number Generator configuration
+#
+
+menuconfig LRNG
+	bool "Linux Random Number Generator"
+	help
+	  The Linux Random Number Generator (LRNG) is the replacement
+	  of the existing /dev/random provided with drivers/char/random.c.
+	  It generates entropy from different noise sources and
+	  delivers significant entropy during boot.
+
+if LRNG
+
+choice
+	prompt "LRNG Entropy Pool Size"
+	default LRNG_POOL_SIZE_4096
+	help
+	  Select the size of the LRNG entropy pool. The size of the
+	  entropy pool is relevant for the amount of entropy that
+	  the LRNG can maintain as a maximum. The larger the size
+	  of the entropy pool is the more entropy can be maintained
+	  but the less often older entropic values are overwritten
+	  with new entropy.
+
+	config LRNG_POOL_SIZE_512
+		bool "512 bits"
+
+	config LRNG_POOL_SIZE_1024
+		bool "1024 bits"
+
+	config LRNG_POOL_SIZE_2048
+		bool "2048 bits"
+
+	config LRNG_POOL_SIZE_4096
+		bool "4096 bits (default)"
+
+	config LRNG_POOL_SIZE_8192
+		bool "8192 bits"
+
+	config LRNG_POOL_SIZE_16384
+		bool "16384 bits"
+
+	config LRNG_POOL_SIZE_32768
+		bool "32768 bits"
+
+	config LRNG_POOL_SIZE_65536
+		bool "65536 bits"
+
+	config LRNG_POOL_SIZE_131072
+		bool "131072 bits"
+endchoice
+
+config LRNG_POOL_SIZE
+	int
+	default 0 if LRNG_POOL_SIZE_512
+	default 1 if LRNG_POOL_SIZE_1024
+	default 2 if LRNG_POOL_SIZE_2048
+	default 3 if LRNG_POOL_SIZE_4096
+	default 4 if LRNG_POOL_SIZE_8192
+	default 5 if LRNG_POOL_SIZE_16384
+	default 6 if LRNG_POOL_SIZE_32768
+	default 7 if LRNG_POOL_SIZE_65536
+	default 8 if LRNG_POOL_SIZE_131072
+
+endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
new file mode 100644
index 000000000000..1d2a0211973d
--- /dev/null
+++ b/drivers/char/lrng/Makefile
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for the Linux Random Number Generator.
+#
+
+obj-y				+= lrng_pool.o lrng_aux.o \
+				   lrng_sw_noise.o lrng_archrandom.o \
+				   lrng_drng.o lrng_chacha20.o \
+				   lrng_interfaces.o \
diff --git a/drivers/char/lrng/lrng_archrandom.c b/drivers/char/lrng/lrng_archrandom.c
new file mode 100644
index 000000000000..ec6f17d976e3
--- /dev/null
+++ b/drivers/char/lrng/lrng_archrandom.c
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG Fast Noise Source: CPU-based noise source
+ *
+ * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/random.h>
+
+#include "lrng_internal.h"
+
+/*
+ * Estimated entropy of data is a 32th of LRNG_DRNG_SECURITY_STRENGTH_BITS.
+ * As we have no ability to review the implementation of those noise sources,
+ * it is prudent to have a conservative estimate here.
+ */
+#define LRNG_ARCHRANDOM_DEFAULT_STRENGTH (LRNG_DRNG_SECURITY_STRENGTH_BITS>>5)
+#define LRNG_ARCHRANDOM_TRUST_CPU_STRENGTH LRNG_DRNG_SECURITY_STRENGTH_BITS
+#ifdef CONFIG_RANDOM_TRUST_CPU
+static u32 archrandom = LRNG_ARCHRANDOM_TRUST_CPU_STRENGTH;
+#else
+static u32 archrandom = LRNG_ARCHRANDOM_DEFAULT_STRENGTH;
+#endif
+module_param(archrandom, uint, 0644);
+MODULE_PARM_DESC(archrandom, "Entropy in bits of 256 data bits from CPU noise "
+			     "source (e.g. RDRAND)");
+
+static int __init lrng_parse_trust_cpu(char *arg)
+{
+	int ret;
+	bool trust_cpu = false;
+
+	ret = kstrtobool(arg, &trust_cpu);
+	if (ret)
+		return ret;
+
+	if (trust_cpu)
+		archrandom = LRNG_ARCHRANDOM_TRUST_CPU_STRENGTH;
+	else
+		archrandom = LRNG_ARCHRANDOM_DEFAULT_STRENGTH;
+
+	return 0;
+}
+early_param("random.trust_cpu", lrng_parse_trust_cpu);
+
+/**
+ * Get CPU noise source entropy
+ *
+ * @outbuf: buffer to store entropy of size LRNG_DRNG_SECURITY_STRENGTH_BYTES
+ * @return: > 0 on success where value provides the added entropy in bits
+ *	    0 if no fast source was available
+ */
+u32 lrng_get_arch(u8 *outbuf)
+{
+	u32 i, ent_bits = archrandom;
+
+	/* operate on full blocks */
+	BUILD_BUG_ON(LRNG_DRNG_SECURITY_STRENGTH_BYTES % sizeof(unsigned long));
+	/* ensure we have aligned buffers */
+	BUILD_BUG_ON(LRNG_KCAPI_ALIGN % sizeof(unsigned long));
+
+	if (!ent_bits)
+		return 0;
+
+	for (i = 0; i < LRNG_DRNG_SECURITY_STRENGTH_BYTES;
+	     i += sizeof(unsigned long)) {
+		if (!arch_get_random_seed_long((unsigned long *)(outbuf + i)) &&
+		    !arch_get_random_long((unsigned long *)(outbuf + i))) {
+			archrandom = 0;
+			return 0;
+		}
+	}
+
+	/* Obtain entropy statement -- cap entropy to buffer size in bits */
+	ent_bits = min_t(u32, ent_bits, LRNG_DRNG_SECURITY_STRENGTH_BITS);
+	pr_debug("obtained %u bits of entropy from CPU RNG noise source\n",
+		 ent_bits);
+	return ent_bits;
+}
+
+u32 lrng_slow_noise_req_entropy(u32 required_entropy_bits)
+{
+	u32 arch_ent_bits = min_t(u32, archrandom,
+				  LRNG_DRNG_SECURITY_STRENGTH_BITS);
+	u32 fast_noise_entropy = arch_ent_bits + lrng_jent_entropylevel();
+
+	if (fast_noise_entropy > required_entropy_bits)
+		return 0;
+	return (required_entropy_bits - fast_noise_entropy);
+}
diff --git a/drivers/char/lrng/lrng_aux.c b/drivers/char/lrng/lrng_aux.c
new file mode 100644
index 000000000000..b66c7795d067
--- /dev/null
+++ b/drivers/char/lrng/lrng_aux.c
@@ -0,0 +1,148 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG auxiliary interfaces
+ *
+ * Copyright (C) 2019 Stephan Mueller <smueller@chronox.de>
+ * Copyright (C) 2017 Jason A. Donenfeld <Jason@zx2c4.com>. All
+ * Rights Reserved.
+ * Copyright (C) 2016 Jason Cooper <jason@lakedaemon.net>
+ */
+
+#include <linux/mm.h>
+#include <linux/random.h>
+
+#include "lrng_internal.h"
+
+struct batched_entropy {
+	union {
+		u64 entropy_u64[LRNG_DRNG_BLOCKSIZE / sizeof(u64)];
+		u32 entropy_u32[LRNG_DRNG_BLOCKSIZE / sizeof(u32)];
+	};
+	unsigned int position;
+	spinlock_t batch_lock;
+};
+
+/*
+ * Get a random word for internal kernel use only. The quality of the random
+ * number is either as good as RDRAND or as good as /dev/urandom, with the
+ * goal of being quite fast and not depleting entropy.
+ */
+static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_u64) = {
+	.batch_lock	= __SPIN_LOCK_UNLOCKED(batched_entropy_u64.lock),
+};
+
+u64 get_random_u64(void)
+{
+	u64 ret;
+	unsigned long flags;
+	struct batched_entropy *batch;
+
+#if BITS_PER_LONG == 64
+	if (arch_get_random_long((unsigned long *)&ret))
+		return ret;
+#else
+	if (arch_get_random_long((unsigned long *)&ret) &&
+	    arch_get_random_long((unsigned long *)&ret + 1))
+		return ret;
+#endif
+
+	lrng_debug_report_seedlevel("get_random_u64");
+
+	batch = raw_cpu_ptr(&batched_entropy_u64);
+	spin_lock_irqsave(&batch->batch_lock, flags);
+	if (batch->position % ARRAY_SIZE(batch->entropy_u64) == 0) {
+		lrng_drng_get_atomic((u8 *)batch->entropy_u64,
+				      LRNG_DRNG_BLOCKSIZE);
+		batch->position = 0;
+	}
+	ret = batch->entropy_u64[batch->position++];
+	spin_unlock_irqrestore(&batch->batch_lock, flags);
+	return ret;
+}
+EXPORT_SYMBOL(get_random_u64);
+
+static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_u32) = {
+	.batch_lock	= __SPIN_LOCK_UNLOCKED(batched_entropy_u32.lock),
+};
+
+u32 get_random_u32(void)
+{
+	u32 ret;
+	unsigned long flags;
+	struct batched_entropy *batch;
+
+	if (arch_get_random_int(&ret))
+		return ret;
+
+	lrng_debug_report_seedlevel("get_random_u32");
+
+	batch = raw_cpu_ptr(&batched_entropy_u32);
+	spin_lock_irqsave(&batch->batch_lock, flags);
+	if (batch->position % ARRAY_SIZE(batch->entropy_u32) == 0) {
+		lrng_drng_get_atomic((u8 *)batch->entropy_u32,
+				      LRNG_DRNG_BLOCKSIZE);
+		batch->position = 0;
+	}
+	ret = batch->entropy_u32[batch->position++];
+	spin_unlock_irqrestore(&batch->batch_lock, flags);
+	return ret;
+}
+EXPORT_SYMBOL(get_random_u32);
+
+/*
+ * It's important to invalidate all potential batched entropy that might
+ * be stored before the crng is initialized, which we can do lazily by
+ * simply resetting the counter to zero so that it's re-extracted on the
+ * next usage.
+ */
+void invalidate_batched_entropy(void)
+{
+	int cpu;
+	unsigned long flags;
+
+	for_each_possible_cpu(cpu) {
+		struct batched_entropy *batched_entropy;
+
+		batched_entropy = per_cpu_ptr(&batched_entropy_u32, cpu);
+		spin_lock_irqsave(&batched_entropy->batch_lock, flags);
+		batched_entropy->position = 0;
+		spin_unlock(&batched_entropy->batch_lock);
+
+		batched_entropy = per_cpu_ptr(&batched_entropy_u64, cpu);
+		spin_lock(&batched_entropy->batch_lock);
+		batched_entropy->position = 0;
+		spin_unlock_irqrestore(&batched_entropy->batch_lock, flags);
+	}
+}
+
+/**
+ * randomize_page - Generate a random, page aligned address
+ * @start:	The smallest acceptable address the caller will take.
+ * @range:	The size of the area, starting at @start, within which the
+ *		random address must fall.
+ *
+ * If @start + @range would overflow, @range is capped.
+ *
+ * NOTE: Historical use of randomize_range, which this replaces, presumed that
+ * @start was already page aligned.  We now align it regardless.
+ *
+ * Return: A page aligned address within [start, start + range).  On error,
+ * @start is returned.
+ */
+unsigned long randomize_page(unsigned long start, unsigned long range)
+{
+	if (!PAGE_ALIGNED(start)) {
+		range -= PAGE_ALIGN(start) - start;
+		start = PAGE_ALIGN(start);
+	}
+
+	if (start > ULONG_MAX - range)
+		range = ULONG_MAX - start;
+
+	range >>= PAGE_SHIFT;
+
+	if (range == 0)
+		return start;
+
+	return start + (get_random_long() % range << PAGE_SHIFT);
+}
diff --git a/drivers/char/lrng/lrng_chacha20.c b/drivers/char/lrng/lrng_chacha20.c
new file mode 100644
index 000000000000..6b91545893ed
--- /dev/null
+++ b/drivers/char/lrng/lrng_chacha20.c
@@ -0,0 +1,317 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * Backend for the LRNG providing the cryptographic primitives using
+ * ChaCha20 cipher implementations.
+ *
+ * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <crypto/chacha.h>
+#include <linux/cryptohash.h>
+#include <linux/lrng.h>
+#include <linux/random.h>
+#include <linux/slab.h>
+
+#include "lrng_chacha20.h"
+#include "lrng_internal.h"
+
+/******************************* ChaCha20 DRNG *******************************/
+
+#define CHACHA_BLOCK_WORDS	(CHACHA_BLOCK_SIZE / sizeof(u32))
+
+struct chacha20_state {
+	struct chacha20_block block;
+};
+
+/*
+ * Have a static memory blocks for the ChaCha20 DRNG instance to avoid calling
+ * kmalloc too early in the boot cycle. For subsequent allocation requests,
+ * such as per-NUMA-node DRNG instances, kmalloc will be used.
+ */
+struct chacha20_state chacha20;
+
+/**
+ * Update of the ChaCha20 state by either using an unused buffer part or by
+ * generating one ChaCha20 block which is half of the state of the ChaCha20.
+ * The block is XORed into the key part of the state. This shall ensure
+ * backtracking resistance as well as a proper mix of the ChaCha20 state once
+ * the key is injected.
+ */
+static void lrng_chacha20_update(struct chacha20_state *chacha20_state,
+				 u32 *buf, u32 used_words)
+{
+	struct chacha20_block *chacha20 = &chacha20_state->block;
+	u32 i, tmp[CHACHA_BLOCK_WORDS];
+
+	BUILD_BUG_ON(sizeof(struct chacha20_block) != CHACHA_BLOCK_SIZE);
+	BUILD_BUG_ON(CHACHA_BLOCK_SIZE != 2 * CHACHA_KEY_SIZE);
+
+	if (used_words > CHACHA_KEY_SIZE_WORDS) {
+		chacha20_block(&chacha20->constants[0], (u8 *)tmp);
+		for (i = 0; i < CHACHA_KEY_SIZE_WORDS; i++)
+			chacha20->key.u[i] ^= tmp[i];
+		memzero_explicit(tmp, sizeof(tmp));
+	} else {
+		for (i = 0; i < CHACHA_KEY_SIZE_WORDS; i++)
+			chacha20->key.u[i] ^= buf[i + used_words];
+	}
+
+	/* Deterministic increment of nonce as required in RFC 7539 chapter 4 */
+	chacha20->nonce[0]++;
+	if (chacha20->nonce[0] == 0)
+		chacha20->nonce[1]++;
+	if (chacha20->nonce[1] == 0)
+		chacha20->nonce[2]++;
+
+	/* Leave counter untouched as it is start value is undefined in RFC */
+}
+
+/**
+ * Seed the ChaCha20 DRNG by injecting the input data into the key part of
+ * the ChaCha20 state. If the input data is longer than the ChaCha20 key size,
+ * perform a ChaCha20 operation after processing of key size input data.
+ * This operation shall spread out the entropy into the ChaCha20 state before
+ * new entropy is injected into the key part.
+ */
+static int lrng_cc20_drng_seed_helper(void *drng, const u8 *inbuf, u32 inbuflen)
+{
+	struct chacha20_state *chacha20_state = (struct chacha20_state *)drng;
+	struct chacha20_block *chacha20 = &chacha20_state->block;
+
+	while (inbuflen) {
+		u32 i, todo = min_t(u32, inbuflen, CHACHA_KEY_SIZE);
+
+		for (i = 0; i < todo; i++)
+			chacha20->key.b[i] ^= inbuf[i];
+
+		/* Break potential dependencies between the inbuf key blocks */
+		lrng_chacha20_update(chacha20_state, NULL,
+				     CHACHA_BLOCK_WORDS);
+		inbuf += todo;
+		inbuflen -= todo;
+	}
+
+	return 0;
+}
+
+/**
+ * Chacha20 DRNG generation of random numbers: the stream output of ChaCha20
+ * is the random number. After the completion of the generation of the
+ * stream, the entire ChaCha20 state is updated.
+ *
+ * Note, as the ChaCha20 implements a 32 bit counter, we must ensure
+ * that this function is only invoked for at most 2^32 - 1 ChaCha20 blocks
+ * before a reseed or an update happens. This is ensured by the variable
+ * outbuflen which is a 32 bit integer defining the number of bytes to be
+ * generated by the ChaCha20 DRNG. At the end of this function, an update
+ * operation is invoked which implies that the 32 bit counter will never be
+ * overflown in this implementation.
+ */
+static int lrng_cc20_drng_generate_helper(void *drng, u8 *outbuf, u32 outbuflen)
+{
+	struct chacha20_state *chacha20_state = (struct chacha20_state *)drng;
+	struct chacha20_block *chacha20 = &chacha20_state->block;
+	u32 aligned_buf[CHACHA_BLOCK_WORDS], ret = outbuflen,
+	    used = CHACHA_BLOCK_WORDS;
+	int zeroize_buf = 0;
+
+	while (outbuflen >= CHACHA_BLOCK_SIZE) {
+		chacha20_block(&chacha20->constants[0], outbuf);
+		outbuf += CHACHA_BLOCK_SIZE;
+		outbuflen -= CHACHA_BLOCK_SIZE;
+	}
+
+	if (outbuflen) {
+		chacha20_block(&chacha20->constants[0], (u8 *)aligned_buf);
+		memcpy(outbuf, aligned_buf, outbuflen);
+		used = ((outbuflen + sizeof(aligned_buf[0]) - 1) /
+			sizeof(aligned_buf[0]));
+		zeroize_buf = 1;
+	}
+
+	lrng_chacha20_update(chacha20_state, aligned_buf, used);
+
+	if (zeroize_buf)
+		memzero_explicit(aligned_buf, sizeof(aligned_buf));
+
+	return ret;
+}
+
+/**
+ * ChaCha20 DRNG that provides full strength, i.e. the output is capable
+ * of transporting 1 bit of entropy per data bit, provided the DRNG was
+ * seeded with 256 bits of entropy. This is achieved by folding the ChaCha20
+ * block output of 512 bits in half using XOR.
+ *
+ * Other than the output handling, the implementation is conceptually
+ * identical to lrng_drng_generate_helper.
+ */
+static int lrng_cc20_drng_generate_helper_full(void *drng, u8 *outbuf,
+					       u32 outbuflen)
+{
+	struct chacha20_state *chacha20_state = (struct chacha20_state *)drng;
+	struct chacha20_block *chacha20 = &chacha20_state->block;
+	u32 aligned_buf[CHACHA_BLOCK_WORDS];
+	u32 ret = outbuflen;
+
+	while (outbuflen >= CHACHA_BLOCK_SIZE) {
+		u32 i;
+
+		chacha20_block(&chacha20->constants[0], outbuf);
+
+		/* fold output in half */
+		for (i = 0; i < (CHACHA_BLOCK_WORDS / 2); i++)
+			outbuf[i] ^= outbuf[i + (CHACHA_BLOCK_WORDS / 2)];
+
+		outbuf += CHACHA_BLOCK_SIZE / 2;
+		outbuflen -= CHACHA_BLOCK_SIZE / 2;
+	}
+
+	while (outbuflen) {
+		u32 i, todo = min_t(u32, CHACHA_BLOCK_SIZE / 2, outbuflen);
+
+		chacha20_block(&chacha20->constants[0], (u8 *)aligned_buf);
+
+		/* fold output in half */
+		for (i = 0; i < (CHACHA_BLOCK_WORDS / 2); i++)
+			aligned_buf[i] ^=
+				aligned_buf[i + (CHACHA_BLOCK_WORDS / 2)];
+
+		memcpy(outbuf, aligned_buf, todo);
+		outbuflen -= todo;
+		outbuf += todo;
+	}
+	memzero_explicit(aligned_buf, sizeof(aligned_buf));
+
+	lrng_chacha20_update(chacha20_state, NULL, CHACHA_BLOCK_WORDS);
+
+	return ret;
+}
+
+void lrng_cc20_init_state(struct chacha20_state *state)
+{
+	struct chacha20_block *chacha20 = &state->block;
+	unsigned long v;
+	u32 i;
+
+	lrng_cc20_init_rfc7539(chacha20);
+
+	for (i = 0; i < CHACHA_KEY_SIZE_WORDS; i++) {
+		chacha20->key.u[i] ^= jiffies;
+		chacha20->key.u[i] ^= random_get_entropy();
+		if (arch_get_random_seed_long(&v) || arch_get_random_long(&v))
+			chacha20->key.u[i] ^= v;
+	}
+
+	for (i = 0; i < 3; i++) {
+		chacha20->nonce[i] ^= jiffies;
+		chacha20->nonce[i] ^= random_get_entropy();
+		if (arch_get_random_seed_long(&v) || arch_get_random_long(&v))
+			chacha20->nonce[i] ^= v;
+	}
+
+	pr_info("ChaCha20 core initialized\n");
+}
+
+/**
+ * Allocation of the DRNG state
+ */
+static void *lrng_cc20_drng_alloc(u32 sec_strength)
+{
+	struct chacha20_state *state = NULL;
+
+	if (sec_strength > CHACHA_KEY_SIZE) {
+		pr_err("Security strength of ChaCha20 DRNG (%u bits) lower "
+		       "than requested by LRNG (%u bits)\n",
+			CHACHA_KEY_SIZE * 8, sec_strength * 8);
+		return ERR_PTR(-EINVAL);
+	}
+	if (sec_strength < CHACHA_KEY_SIZE)
+		pr_warn("Security strength of ChaCha20 DRNG (%u bits) higher "
+			"than requested by LRNG (%u bits)\n",
+			CHACHA_KEY_SIZE * 8, sec_strength * 8);
+
+	state = kmalloc(sizeof(struct chacha20_state), GFP_KERNEL);
+	if (!state)
+		return ERR_PTR(-ENOMEM);
+	pr_debug("memory for ChaCha20 core allocated\n");
+
+	lrng_cc20_init_state(state);
+
+	return state;
+}
+
+static void lrng_cc20_drng_dealloc(void *drng)
+{
+	struct chacha20_state *chacha20_state = (struct chacha20_state *)drng;
+
+	if (drng == &chacha20) {
+		memzero_explicit(chacha20_state, sizeof(*chacha20_state));
+		pr_debug("static ChaCha20 core zeroized\n");
+		return;
+	}
+
+	pr_debug("ChaCha20 core zeroized and freed\n");
+	kzfree(chacha20_state);
+}
+
+/******************************* Hash Operation *******************************/
+
+static void *lrng_cc20_hash_alloc(const u8 *key, u32 keylen)
+{
+	pr_info("Hash SHA-1 allocated\n");
+	return NULL;
+}
+
+static void lrng_cc20_hash_dealloc(void *hash)
+{
+}
+
+static u32 lrng_cc20_hash_digestsize(void *hash)
+{
+	return (SHA_DIGEST_WORDS * sizeof(u32));
+}
+
+static int lrng_cc20_hash_buffer(void *hash, const u8 *inbuf, u32 inbuflen,
+				 u8 *digest)
+{
+	u32 i;
+	u32 workspace[SHA_WORKSPACE_WORDS];
+
+	WARN_ON(inbuflen % (SHA_WORKSPACE_WORDS * sizeof(u32)));
+
+	sha_init((u32 *)digest);
+	for (i = 0; i < inbuflen; i += (SHA_WORKSPACE_WORDS * sizeof(u32)))
+		sha_transform((u32 *)digest, (inbuf + i), workspace);
+	memzero_explicit(workspace, sizeof(workspace));
+
+	return 0;
+}
+
+static const char *lrng_cc20_drng_name(void)
+{
+	const char *cc20_drng_name = "ChaCha20 DRNG";
+	return cc20_drng_name;
+}
+
+static const char *lrng_cc20_hash_name(void)
+{
+	const char *cc20_hash_name = "SHA-1";
+	return cc20_hash_name;
+}
+
+const struct lrng_crypto_cb lrng_cc20_crypto_cb = {
+	.lrng_drng_name			= lrng_cc20_drng_name,
+	.lrng_hash_name			= lrng_cc20_hash_name,
+	.lrng_drng_alloc		= lrng_cc20_drng_alloc,
+	.lrng_drng_dealloc		= lrng_cc20_drng_dealloc,
+	.lrng_drng_seed_helper		= lrng_cc20_drng_seed_helper,
+	.lrng_drng_generate_helper	= lrng_cc20_drng_generate_helper,
+	.lrng_drng_generate_helper_full	= lrng_cc20_drng_generate_helper_full,
+	.lrng_hash_alloc		= lrng_cc20_hash_alloc,
+	.lrng_hash_dealloc		= lrng_cc20_hash_dealloc,
+	.lrng_hash_digestsize		= lrng_cc20_hash_digestsize,
+	.lrng_hash_buffer		= lrng_cc20_hash_buffer,
+};
diff --git a/drivers/char/lrng/lrng_chacha20.h b/drivers/char/lrng/lrng_chacha20.h
new file mode 100644
index 000000000000..0387ad59cfbc
--- /dev/null
+++ b/drivers/char/lrng/lrng_chacha20.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
+/*
+ * LRNG ChaCha20 definitions
+ *
+ * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#include <crypto/chacha.h>
+
+/* State according to RFC 7539 section 2.3 */
+struct chacha20_block {
+	u32 constants[4];
+	union {
+#define CHACHA_KEY_SIZE_WORDS (CHACHA_KEY_SIZE / sizeof(u32))
+		u32 u[CHACHA_KEY_SIZE_WORDS];
+		u8  b[CHACHA_KEY_SIZE];
+	} key;
+	u32 counter;
+	u32 nonce[3];
+};
+
+static inline void lrng_cc20_init_rfc7539(struct chacha20_block *chacha20)
+{
+	memcpy(&chacha20->constants[0], "expand 32-byte k", 16);
+}
diff --git a/drivers/char/lrng/lrng_drng.c b/drivers/char/lrng/lrng_drng.c
new file mode 100644
index 000000000000..b55f4ad7580c
--- /dev/null
+++ b/drivers/char/lrng/lrng_drng.c
@@ -0,0 +1,397 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG DRNG processing
+ *
+ * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/lrng.h>
+
+#include "lrng_internal.h"
+
+/*
+ * Maximum number of seconds between DRNG reseed intervals of the DRNG. Note,
+ * this is enforced with the next request of random numbers from the
+ * DRNG. Setting this value to zero implies a reseeding attempt before every
+ * generated random number.
+ */
+int lrng_drng_reseed_max_time = 600;
+
+static atomic_t lrng_avail = ATOMIC_INIT(0);
+
+DEFINE_MUTEX(lrng_crypto_cb_update);
+
+/* DRNG for /dev/urandom, getrandom(2), get_random_bytes */
+static struct lrng_drng lrng_drng_init = {
+	.drng		= &chacha20,
+	.crypto_cb	= &lrng_cc20_crypto_cb,
+	.lock		= __MUTEX_INITIALIZER(lrng_drng_init.lock),
+	.spin_lock	= __SPIN_LOCK_UNLOCKED(lrng_drng_init.spin_lock)
+};
+
+/*
+ * DRNG for get_random_bytes when called in atomic context. This
+ * DRNG will always use the ChaCha20 DRNG. It will never benefit from a
+ * DRNG switch like the "regular" DRNG. If there was no DRNG switch, the atomic
+ * DRNG is identical to the "regular" DRNG.
+ *
+ * The reason for having this is due to the fact that DRNGs other than
+ * the ChaCha20 DRNG may sleep.
+ */
+static struct lrng_drng lrng_drng_atomic = {
+	.drng		= &chacha20,
+	.crypto_cb	= &lrng_cc20_crypto_cb,
+	.spin_lock	= __SPIN_LOCK_UNLOCKED(lrng_drng_atomic.spin_lock)
+};
+
+/********************************** Helper ************************************/
+
+bool lrng_get_available(void)
+{
+	return likely(atomic_read(&lrng_avail));
+}
+
+void lrng_set_available(void)
+{
+	atomic_set(&lrng_avail, 1);
+}
+
+struct lrng_drng *lrng_drng_init_instance(void)
+{
+	return &lrng_drng_init;
+}
+
+struct lrng_drng *lrng_drng_atomic_instance(void)
+{
+	return &lrng_drng_atomic;
+}
+
+void lrng_drng_reset(struct lrng_drng *drng)
+{
+	atomic_set(&drng->requests, LRNG_DRNG_RESEED_THRESH);
+	drng->last_seeded = jiffies;
+	drng->fully_seeded = false;
+	drng->force_reseed = true;
+	pr_debug("reset DRNG\n");
+}
+
+/************************* Random Number Generation ***************************/
+
+/* Inject a data buffer into the DRNG */
+static void lrng_drng_inject(struct lrng_drng *drng,
+			     const u8 *inbuf, u32 inbuflen)
+{
+	const char *drng_type = unlikely(drng == &lrng_drng_atomic) ?
+				"atomic" : "regular";
+	unsigned long flags = 0;
+
+	BUILD_BUG_ON(LRNG_DRNG_RESEED_THRESH > INT_MAX);
+	pr_debug("seeding %s DRNG with %u bytes\n", drng_type, inbuflen);
+	lrng_drng_lock(drng, &flags);
+	if (drng->crypto_cb->lrng_drng_seed_helper(drng->drng,
+						    inbuf, inbuflen) < 0) {
+		pr_warn("seeding of %s DRNG failed\n", drng_type);
+		atomic_set(&drng->requests, 1);
+	} else {
+		pr_debug("%s DRNG stats since last seeding: %lu secs; "
+			 "generate calls: %d\n", drng_type,
+			 (time_after(jiffies, drng->last_seeded) ?
+			  (jiffies - drng->last_seeded) : 0) / HZ,
+			 (LRNG_DRNG_RESEED_THRESH -
+			  atomic_read(&drng->requests)));
+		drng->last_seeded = jiffies;
+		atomic_set(&drng->requests, LRNG_DRNG_RESEED_THRESH);
+		drng->force_reseed = false;
+
+		if (drng->drng == lrng_drng_atomic.drng) {
+			lrng_drng_atomic.last_seeded = jiffies;
+			atomic_set(&lrng_drng_atomic.requests,
+				   LRNG_DRNG_RESEED_THRESH);
+			lrng_drng_atomic.force_reseed = false;
+		}
+	}
+	lrng_drng_unlock(drng, &flags);
+}
+
+/**
+ * Perform the seeding of the DRNG with data from noise source
+ */
+static inline int _lrng_drng_seed(struct lrng_drng *drng)
+{
+	struct entropy_buf seedbuf __aligned(LRNG_KCAPI_ALIGN);
+	unsigned long flags = 0;
+	u32 total_entropy_bits;
+	int ret;
+
+	lrng_drng_lock(drng, &flags);
+	total_entropy_bits = lrng_fill_seed_buffer(drng->crypto_cb, drng->hash,
+						   &seedbuf, 0);
+	lrng_drng_unlock(drng, &flags);
+
+	/* Allow the seeding operation to be called again */
+	lrng_pool_unlock();
+	lrng_init_ops(total_entropy_bits);
+	ret = total_entropy_bits >> 3;
+
+	lrng_drng_inject(drng, (u8 *)&seedbuf, sizeof(seedbuf));
+	memzero_explicit(&seedbuf, sizeof(seedbuf));
+
+	return ret;
+}
+
+static int lrng_drng_get(struct lrng_drng *drng, u8 *outbuf, u32 outbuflen);
+static void lrng_drng_seed(struct lrng_drng *drng)
+{
+	int ret = _lrng_drng_seed(drng);
+
+	if (ret >= LRNG_DRNG_SECURITY_STRENGTH_BYTES)
+		drng->fully_seeded = true;
+
+	BUILD_BUG_ON(LRNG_MIN_SEED_ENTROPY_BITS >
+		     LRNG_DRNG_SECURITY_STRENGTH_BITS);
+
+	/*
+	 * Reseed atomic DRNG from current DRNG,
+	 *
+	 * We can obtain random numbers from DRNG as the lock type
+	 * chosen by lrng_drng_get is usable with the current caller.
+	 */
+	if ((drng->drng != lrng_drng_atomic.drng) &&
+	    (lrng_drng_atomic.force_reseed ||
+	     atomic_read(&lrng_drng_atomic.requests) <= 0 ||
+	     time_after(jiffies, lrng_drng_atomic.last_seeded +
+			lrng_drng_reseed_max_time * HZ))) {
+		u8 seedbuf[LRNG_DRNG_SECURITY_STRENGTH_BYTES]
+						__aligned(LRNG_KCAPI_ALIGN);
+
+		ret = lrng_drng_get(drng, seedbuf, sizeof(seedbuf));
+
+		if (ret < 0) {
+			pr_warn("Error generating random numbers for atomic "
+				"DRNG: %d\n", ret);
+		} else {
+			lrng_drng_inject(&lrng_drng_atomic, seedbuf, ret);
+		}
+		memzero_explicit(&seedbuf, sizeof(seedbuf));
+	}
+}
+
+static inline void _lrng_drng_seed_work(struct lrng_drng *drng, u32 node)
+{
+	pr_debug("reseed triggered by interrupt noise source for DRNG on NUMA "
+		 "node %d\n", node);
+	lrng_drng_seed(drng);
+	if (drng->fully_seeded) {
+		/* Prevent reseed storm */
+		drng->last_seeded += node * 100 * HZ;
+		/* Prevent draining of pool on idle systems */
+		lrng_drng_reseed_max_time += 100;
+	}
+}
+
+/**
+ * DRNG reseed trigger: Kernel thread handler triggered by the schedule_work()
+ */
+void lrng_drng_seed_work(struct work_struct *dummy)
+{
+	struct lrng_drng **lrng_drng = lrng_drng_instances();
+	u32 node;
+
+	if (lrng_drng) {
+		for_each_online_node(node) {
+			struct lrng_drng *drng = lrng_drng[node];
+
+			if (drng && !drng->fully_seeded) {
+				_lrng_drng_seed_work(drng, node);
+				goto out;
+			}
+		}
+		lrng_pool_all_numa_nodes_seeded();
+	} else {
+		if (!lrng_drng_init.fully_seeded)
+			_lrng_drng_seed_work(&lrng_drng_init, 0);
+	}
+
+out:
+	/* Allow the seeding operation to be called again */
+	lrng_pool_unlock();
+}
+
+/* Force all DRNGs to reseed before next generation */
+void lrng_drng_force_reseed(void)
+{
+	struct lrng_drng **lrng_drng = lrng_drng_instances();
+	u32 node;
+
+	if (!lrng_drng) {
+		lrng_drng_init.force_reseed = true;
+		pr_debug("force reseed of initial DRNG\n");
+		return;
+	}
+	for_each_online_node(node) {
+		struct lrng_drng *drng = lrng_drng[node];
+
+		if (!drng)
+			continue;
+
+		drng->force_reseed = true;
+		pr_debug("force reseed of DRNG on node %u\n", node);
+	}
+	lrng_drng_atomic.force_reseed = true;
+}
+
+/**
+ * Get random data out of the DRNG which is reseeded frequently.
+ *
+ * @outbuf: buffer for storing random data
+ * @outbuflen: length of outbuf
+ * @return: < 0 in error case (DRNG generation or update failed)
+ *	    >=0 returning the returned number of bytes
+ */
+static int lrng_drng_get(struct lrng_drng *drng, u8 *outbuf, u32 outbuflen)
+{
+	unsigned long flags = 0;
+	u32 processed = 0;
+
+	if (!outbuf || !outbuflen)
+		return 0;
+
+	outbuflen = min_t(size_t, outbuflen, INT_MAX);
+
+	lrng_drngs_init_cc20();
+
+	while (outbuflen) {
+		u32 todo = min_t(u32, outbuflen, LRNG_DRNG_MAX_REQSIZE);
+		int ret;
+
+		/* All but the atomic DRNG are seeded during generation */
+		if (atomic_dec_and_test(&drng->requests) ||
+		    drng->force_reseed ||
+		    time_after(jiffies, drng->last_seeded +
+			       lrng_drng_reseed_max_time * HZ)) {
+			if (likely(drng != &lrng_drng_atomic)) {
+				if (lrng_pool_trylock())
+					atomic_set(&drng->requests, 1);
+				else
+					lrng_drng_seed(drng);
+			}
+		}
+
+		lrng_drng_lock(drng, &flags);
+		ret = drng->crypto_cb->lrng_drng_generate_helper(
+					drng->drng, outbuf + processed, todo);
+		lrng_drng_unlock(drng, &flags);
+		if (ret <= 0) {
+			pr_warn("getting random data from DRNG failed (%d)\n",
+				ret);
+			return -EFAULT;
+		}
+		processed += ret;
+		outbuflen -= ret;
+	}
+
+	return processed;
+}
+
+int lrng_drng_get_atomic(u8 *outbuf, u32 outbuflen)
+{
+	return lrng_drng_get(&lrng_drng_atomic, outbuf, outbuflen);
+}
+
+int lrng_drng_get_sleep(u8 *outbuf, u32 outbuflen)
+{
+	struct lrng_drng **lrng_drng = lrng_drng_instances();
+	struct lrng_drng *drng = &lrng_drng_init;
+	int node = numa_node_id();
+
+	might_sleep();
+
+	if (lrng_drng && lrng_drng[node] && lrng_drng[node]->fully_seeded)
+		drng = lrng_drng[node];
+
+	return lrng_drng_get(drng, outbuf, outbuflen);
+}
+
+/* Initialize the default DRNG during boot */
+void lrng_drngs_init_cc20(void)
+{
+	unsigned long flags = 0;
+
+	if (lrng_get_available())
+		return;
+
+	lrng_drng_lock(&lrng_drng_init, &flags);
+	if (lrng_get_available()) {
+		lrng_drng_unlock(&lrng_drng_init, &flags);
+		return;
+	}
+
+	lrng_drng_reset(&lrng_drng_init);
+	lrng_cc20_init_state(&chacha20);
+	lrng_state_init_seed_work();
+	lrng_drng_unlock(&lrng_drng_init, &flags);
+
+	lrng_drng_lock(&lrng_drng_atomic, &flags);
+	lrng_drng_reset(&lrng_drng_atomic);
+	/*
+	 * We do not initialize the state of the atomic DRNG as it is identical
+	 * to the DRNG at this point.
+	 */
+	lrng_drng_unlock(&lrng_drng_atomic, &flags);
+
+	lrng_set_available();
+}
+
+/* Reset LRNG such that all existing entropy is gone */
+static void _lrng_reset(struct work_struct *work)
+{
+	struct lrng_drng **lrng_drng = lrng_drng_instances();
+	unsigned long flags = 0;
+
+	if (!lrng_drng) {
+		lrng_drng_lock(&lrng_drng_init, &flags);
+		lrng_drng_reset(&lrng_drng_init);
+		lrng_drng_unlock(&lrng_drng_init, &flags);
+	} else {
+		u32 node;
+
+		for_each_online_node(node) {
+			struct lrng_drng *drng = lrng_drng[node];
+
+			if (!drng)
+				continue;
+			lrng_drng_lock(drng, &flags);
+			lrng_drng_reset(drng);
+			lrng_drng_unlock(drng, &flags);
+		}
+	}
+	lrng_set_entropy_thresh(LRNG_INIT_ENTROPY_BITS +
+				LRNG_CONDITIONING_ENTROPY_LOSS);
+
+	lrng_reset_state();
+}
+
+static DECLARE_WORK(lrng_reset_work, _lrng_reset);
+
+void lrng_reset(void)
+{
+	schedule_work(&lrng_reset_work);
+}
+
+/***************************** Initialize LRNG *******************************/
+
+static int __init lrng_init(void)
+{
+	lrng_drngs_init_cc20();
+
+	lrng_drngs_numa_alloc();
+	return 0;
+}
+
+late_initcall(lrng_init);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
+MODULE_DESCRIPTION("Linux Random Number Generator");
diff --git a/drivers/char/lrng/lrng_interfaces.c b/drivers/char/lrng/lrng_interfaces.c
new file mode 100644
index 000000000000..ff40ed37ddd6
--- /dev/null
+++ b/drivers/char/lrng/lrng_interfaces.c
@@ -0,0 +1,623 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG User and kernel space interfaces
+ *
+ * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/freezer.h>
+#include <linux/fs.h>
+#include <linux/genhd.h>
+#include <linux/kthread.h>
+#include <linux/poll.h>
+#include <linux/preempt.h>
+#include <linux/random.h>
+#include <linux/slab.h>
+#include <linux/syscalls.h>
+#include <linux/timex.h>
+
+#include "lrng_internal.h"
+
+/*
+ * If the entropy count falls under this number of bits, then we
+ * should wake up processes which are selecting or polling on write
+ * access to /dev/random.
+ */
+u32 lrng_write_wakeup_bits = LRNG_WRITE_WAKEUP_ENTROPY;
+
+static LIST_HEAD(lrng_ready_list);
+static DEFINE_SPINLOCK(lrng_ready_list_lock);
+
+static DECLARE_WAIT_QUEUE_HEAD(lrng_write_wait);
+static DECLARE_WAIT_QUEUE_HEAD(lrng_init_wait);
+static struct fasync_struct *fasync;
+
+struct ctl_table random_table[];
+/********************************** Helper ***********************************/
+
+/* Is the DRNG seed level too low? */
+static inline bool lrng_need_entropy(void)
+{
+	return (lrng_avail_entropy() < lrng_write_wakeup_bits);
+}
+
+void lrng_writer_wakeup(void)
+{
+	if (lrng_need_entropy() && wq_has_sleeper(&lrng_write_wait)) {
+		wake_up_interruptible(&lrng_write_wait);
+		kill_fasync(&fasync, SIGIO, POLL_OUT);
+	}
+}
+
+void lrng_init_wakeup(void)
+{
+	wake_up_all(&lrng_init_wait);
+	kill_fasync(&fasync, SIGIO, POLL_IN);
+}
+
+/**
+ * Ping all kernel internal callers waiting until the DRNG is at least minimally
+ * seeded to inform that the DRNG reached that seed level.
+ *
+ * When the SP800-90B testing is enabled, the ping only happens if the SP800-90B
+ * startup health tests are completed. This implies that kernel internal
+ * callers always have an SP800-90B compliant noise source when being
+ * pinged.
+ */
+void lrng_process_ready_list(void)
+{
+	unsigned long flags;
+	struct random_ready_callback *rdy, *tmp;
+
+	if (!lrng_sp80090b_startup_complete())
+		return;
+
+	spin_lock_irqsave(&lrng_ready_list_lock, flags);
+	list_for_each_entry_safe(rdy, tmp, &lrng_ready_list, list) {
+		struct module *owner = rdy->owner;
+
+		list_del_init(&rdy->list);
+		rdy->func(rdy);
+		module_put(owner);
+	}
+	spin_unlock_irqrestore(&lrng_ready_list_lock, flags);
+}
+
+void lrng_debug_report_seedlevel(const char *name)
+{
+#ifdef CONFIG_WARN_ALL_UNSEEDED_RANDOM
+	static void *previous = NULL;
+	void *caller = (void *) _RET_IP_;
+
+	if (READ_ONCE(previous) == caller)
+		return;
+
+	if (!lrng_state_min_seeded())
+		pr_notice("%pS %s called without reaching mimimally seeded "
+			  "level (available entropy %u)\n", caller, name,
+			  lrng_avail_entropy());
+
+	WRITE_ONCE(previous, caller);
+#endif
+}
+
+/************************ LRNG kernel input interfaces ************************/
+
+/**
+ * Interface for in-kernel drivers of true hardware RNGs.
+ * Those devices may produce endless random bits and will be throttled
+ * when our pool is full.
+ *
+ * @buffer: buffer holding the entropic data from HW noise sources to be used to
+ *	    insert into entropy pool.
+ * @count: length of buffer
+ * @entropy_bits: amount of entropy in buffer (value is in bits)
+ */
+void add_hwgenerator_randomness(const char *buffer, size_t count,
+				size_t entropy_bits)
+{
+	/*
+	 * Suspend writing if we are fully loaded with entropy.
+	 * We'll be woken up again once below lrng_write_wakeup_thresh,
+	 * or when the calling thread is about to terminate.
+	 */
+	wait_event_interruptible(lrng_write_wait,
+				lrng_need_entropy() ||
+				lrng_state_exseed_allow(lrng_noise_source_hw) ||
+				kthread_should_stop());
+	lrng_state_exseed_set(lrng_noise_source_hw, false);
+	lrng_pool_lfsr_nonaligned(buffer, count);
+	lrng_pool_add_entropy(entropy_bits);
+}
+EXPORT_SYMBOL_GPL(add_hwgenerator_randomness);
+
+/**
+ * Handle random seed passed by bootloader.
+ * If the seed is trustworthy, it would be regarded as hardware RNGs. Otherwise
+ * it would be regarded as device data.
+ * The decision is controlled by CONFIG_RANDOM_TRUST_BOOTLOADER.
+ *
+ * @buf: buffer holding the entropic data from HW noise sources to be used to
+ *	 insert into entropy pool.
+ * @size: length of buffer
+ */
+void add_bootloader_randomness(const void *buf, unsigned int size)
+{
+	if (IS_ENABLED(CONFIG_RANDOM_TRUST_BOOTLOADER))
+		add_hwgenerator_randomness(buf, size, size * 8);
+	else
+		add_device_randomness(buf, size);
+}
+EXPORT_SYMBOL_GPL(add_bootloader_randomness);
+
+/**
+ * Callback for HID layer -- use the HID event values to stir the entropy pool
+ */
+void add_input_randomness(unsigned int type, unsigned int code,
+			  unsigned int value)
+{
+	static unsigned char last_value;
+
+	/* ignore autorepeat and the like */
+	if (value == last_value)
+		return;
+
+	last_value = value;
+
+	lrng_pool_lfsr_u32((type << 4) ^ code ^ (code >> 4) ^ value);
+}
+EXPORT_SYMBOL_GPL(add_input_randomness);
+
+/**
+ * Add device- or boot-specific data to the entropy pool to help
+ * initialize it.
+ *
+ * None of this adds any entropy; it is meant to avoid the problem of
+ * the entropy pool having similar initial state across largely
+ * identical devices.
+ *
+ * @buf: buffer holding the entropic data from HW noise sources to be used to
+ *	 insert into entropy pool.
+ * @size: length of buffer
+ */
+void add_device_randomness(const void *buf, unsigned int size)
+{
+	lrng_pool_lfsr_nonaligned((u8 *)buf, size);
+	lrng_pool_lfsr_u32(random_get_entropy());
+	lrng_pool_lfsr_u32(jiffies);
+}
+EXPORT_SYMBOL(add_device_randomness);
+
+#ifdef CONFIG_BLOCK
+void rand_initialize_disk(struct gendisk *disk) { }
+void add_disk_randomness(struct gendisk *disk) { }
+EXPORT_SYMBOL(add_disk_randomness);
+#endif
+
+/**
+ * Delete a previously registered readiness callback function.
+ *
+ * @rdy: callback definition that was registered initially
+ */
+void del_random_ready_callback(struct random_ready_callback *rdy)
+{
+	unsigned long flags;
+	struct module *owner = NULL;
+
+	spin_lock_irqsave(&lrng_ready_list_lock, flags);
+	if (!list_empty(&rdy->list)) {
+		list_del_init(&rdy->list);
+		owner = rdy->owner;
+	}
+	spin_unlock_irqrestore(&lrng_ready_list_lock, flags);
+
+	module_put(owner);
+}
+EXPORT_SYMBOL(del_random_ready_callback);
+
+/**
+ * Add a callback function that will be invoked when the DRNG is mimimally
+ * seeded.
+ *
+ * @rdy: callback definition to be invoked when the LRNG is seeded
+ * @return: 0 if callback is successfully added
+ *          -EALREADY if pool is already initialised (callback not called)
+ *	    -ENOENT if module for callback is not alive
+ */
+int add_random_ready_callback(struct random_ready_callback *rdy)
+{
+	struct module *owner;
+	unsigned long flags;
+	int err = -EALREADY;
+
+	if (likely(lrng_state_min_seeded()))
+		return err;
+
+	owner = rdy->owner;
+	if (!try_module_get(owner))
+		return -ENOENT;
+
+	spin_lock_irqsave(&lrng_ready_list_lock, flags);
+	if (lrng_state_min_seeded())
+		goto out;
+
+	owner = NULL;
+
+	list_add(&rdy->list, &lrng_ready_list);
+	err = 0;
+
+out:
+	spin_unlock_irqrestore(&lrng_ready_list_lock, flags);
+
+	module_put(owner);
+
+	return err;
+}
+EXPORT_SYMBOL(add_random_ready_callback);
+
+/*********************** LRNG kernel output interfaces ************************/
+
+/**
+ * Provider of cryptographic strong random numbers for kernel-internal usage.
+ * This function is appropriate for all in-kernel use cases. However,
+ * it will always use the ChaCha20 DRNG.
+ *
+ * @buf: buffer to store the random bytes
+ * @nbytes: size of the buffer
+ */
+void get_random_bytes(void *buf, int nbytes)
+{
+	lrng_drng_get_atomic((u8 *)buf, (u32)nbytes);
+	lrng_debug_report_seedlevel("get_random_bytes");
+}
+EXPORT_SYMBOL(get_random_bytes);
+
+/**
+ * Provider of cryptographic strong random numbers for kernel-internal usage.
+ * This function is appropriate only for non-atomic use cases as this
+ * function may sleep. Though, it provides access to the full functionality
+ * of LRNG including the switchable DRNG support, that may support other
+ * DRNGs such as the SP800-90A DRBG.
+ *
+ * @buf: buffer to store the random bytes
+ * @nbytes: size of the buffer
+ */
+void get_random_bytes_full(void *buf, int nbytes)
+{
+	lrng_drng_get_sleep((u8 *)buf, (u32)nbytes);
+	lrng_debug_report_seedlevel("get_random_bytes_full");
+}
+EXPORT_SYMBOL(get_random_bytes_full);
+
+/**
+ * Wait for the LRNG to be seeded and thus guaranteed to supply
+ * cryptographically secure random numbers. This applies to: the /dev/urandom
+ * device, the get_random_bytes function, and the get_random_{u32,u64,int,long}
+ * family of functions. Using any of these functions without first calling
+ * this function forfeits the guarantee of security.
+ *
+ * Returns: 0 if the LRNG has been seeded.
+ *          -ERESTARTSYS if the function was interrupted by a signal.
+ */
+int wait_for_random_bytes(void)
+{
+	if (likely(lrng_state_min_seeded()))
+		return 0;
+	return wait_event_interruptible(lrng_init_wait,
+					lrng_state_min_seeded());
+}
+EXPORT_SYMBOL(wait_for_random_bytes);
+
+/**
+ * This function will use the architecture-specific hardware random
+ * number generator if it is available.  The arch-specific hw RNG will
+ * almost certainly be faster than what we can do in software, but it
+ * is impossible to verify that it is implemented securely (as
+ * opposed, to, say, the AES encryption of a sequence number using a
+ * key known by the NSA).  So it's useful if we need the speed, but
+ * only if we're willing to trust the hardware manufacturer not to
+ * have put in a back door.
+ *
+ * @buf: buffer allocated by caller to store the random data in
+ * @nbytes: length of outbuf
+ *
+ * Return number of bytes filled in.
+ */
+int __must_check get_random_bytes_arch(void *buf, int nbytes)
+{
+	u8 *p = buf;
+
+	while (nbytes) {
+		unsigned long v;
+		int chunk = min_t(int, nbytes, sizeof(unsigned long));
+
+		if (!arch_get_random_long(&v))
+			break;
+
+		memcpy(p, &v, chunk);
+		p += chunk;
+		nbytes -= chunk;
+	}
+
+	if (nbytes)
+		lrng_drng_get_atomic((u8 *)p, (u32)nbytes);
+
+	return nbytes;
+}
+EXPORT_SYMBOL(get_random_bytes_arch);
+
+/************************ LRNG user output interfaces *************************/
+
+static ssize_t lrng_read_common(char __user *buf, size_t nbytes)
+{
+	ssize_t ret = 0;
+	u8 tmpbuf[LRNG_DRNG_BLOCKSIZE] __aligned(LRNG_KCAPI_ALIGN);
+	u8 *tmp_large = NULL, *tmp = tmpbuf;
+	u32 tmplen = sizeof(tmpbuf);
+
+	if (nbytes == 0)
+		return 0;
+
+	/*
+	 * Satisfy large read requests -- as the common case are smaller
+	 * request sizes, such as 16 or 32 bytes, avoid a kmalloc overhead for
+	 * those by using the stack variable of tmpbuf.
+	 */
+	if (!IS_ENABLED(CONFIG_BASE_SMALL) && (nbytes > sizeof(tmpbuf))) {
+		tmplen = min_t(u32, nbytes, LRNG_DRNG_MAX_REQSIZE);
+		tmp_large = kmalloc(tmplen + LRNG_KCAPI_ALIGN, GFP_KERNEL);
+		if (!tmp_large)
+			tmplen = sizeof(tmpbuf);
+		else
+			tmp = PTR_ALIGN(tmp_large, LRNG_KCAPI_ALIGN);
+	}
+
+	while (nbytes) {
+		u32 todo = min_t(u32, nbytes, tmplen);
+		int rc = 0;
+
+		/* Reschedule if we received a large request. */
+		if ((tmp_large) && need_resched()) {
+			if (signal_pending(current)) {
+				if (ret == 0)
+					ret = -ERESTARTSYS;
+				break;
+			}
+			schedule();
+		}
+
+		rc = lrng_drng_get_sleep(tmp, todo);
+		if (rc <= 0) {
+			if (rc < 0)
+				ret = rc;
+			break;
+		}
+		if (copy_to_user(buf, tmp, rc)) {
+			ret = -EFAULT;
+			break;
+		}
+
+		nbytes -= rc;
+		buf += rc;
+		ret += rc;
+	}
+
+	/* Wipe data just returned from memory */
+	if (tmp_large)
+		kzfree(tmp_large);
+	else
+		memzero_explicit(tmpbuf, sizeof(tmpbuf));
+
+	return ret;
+}
+
+static ssize_t
+lrng_read_common_block(int nonblock, char __user *buf, size_t nbytes)
+{
+	if (nbytes == 0)
+		return 0;
+
+	if (unlikely(!lrng_state_operational())) {
+		int ret;
+
+		if (nonblock)
+			return -EAGAIN;
+
+		ret = wait_event_interruptible(lrng_init_wait,
+					       lrng_state_operational());
+		if (unlikely(ret))
+			return ret;
+	}
+
+	return lrng_read_common(buf, nbytes);
+}
+
+static ssize_t lrng_drng_read_block(struct file *file, char __user *buf,
+				     size_t nbytes, loff_t *ppos)
+{
+	return lrng_read_common_block(file->f_flags & O_NONBLOCK, buf, nbytes);
+}
+
+static unsigned int lrng_random_poll(struct file *file, poll_table *wait)
+{
+	__poll_t mask;
+
+	poll_wait(file, &lrng_init_wait, wait);
+	poll_wait(file, &lrng_write_wait, wait);
+	mask = 0;
+	if (lrng_state_operational())
+		mask |= EPOLLIN | EPOLLRDNORM;
+	if (lrng_need_entropy() ||
+	    lrng_state_exseed_allow(lrng_noise_source_user))
+		mask |= EPOLLOUT | EPOLLWRNORM;
+	return mask;
+}
+
+static ssize_t lrng_drng_write_common(const char __user *buffer, size_t count,
+				      u32 entropy_bits)
+{
+	ssize_t ret = 0;
+	u8 buf[64] __aligned(LRNG_KCAPI_ALIGN);
+	const char __user *p = buffer;
+	u32 orig_entropy_bits = entropy_bits;
+
+	if (!lrng_get_available())
+		return -EAGAIN;
+
+	count = min_t(size_t, count, INT_MAX);
+	while (count > 0) {
+		size_t bytes = min_t(size_t, count, sizeof(buf));
+		u32 ent = min_t(u32, bytes<<3, entropy_bits);
+
+		if (copy_from_user(&buf, p, bytes))
+			return -EFAULT;
+		/* Inject data into entropy pool */
+		lrng_pool_lfsr(buf, bytes);
+		lrng_pool_add_entropy(ent);
+
+		count -= bytes;
+		p += bytes;
+		ret += bytes;
+		entropy_bits -= ent;
+
+		cond_resched();
+	}
+
+	/* Force reseed of DRNG during next data request. */
+	if (!orig_entropy_bits)
+		lrng_drng_force_reseed();
+
+	return ret;
+}
+
+static ssize_t lrng_drng_read(struct file *file, char __user *buf,
+			      size_t nbytes, loff_t *ppos)
+{
+	if (!lrng_state_min_seeded())
+		pr_notice_ratelimited("%s - use of insufficiently seeded DRNG "
+				      "(%zu bytes read)\n", current->comm,
+				      nbytes);
+	else if (!lrng_state_operational())
+		pr_debug_ratelimited("%s - use of not fully seeded DRNG (%zu "
+				     "bytes read)\n", current->comm, nbytes);
+
+	return lrng_read_common(buf, nbytes);
+}
+
+static ssize_t lrng_drng_write(struct file *file, const char __user *buffer,
+			       size_t count, loff_t *ppos)
+{
+	return lrng_drng_write_common(buffer, count, 0);
+}
+
+static long lrng_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
+{
+	int size, ent_count_bits;
+	int __user *p = (int __user *)arg;
+
+	switch (cmd) {
+	case RNDGETENTCNT:
+		ent_count_bits = lrng_avail_entropy();
+		if (put_user(ent_count_bits, p))
+			return -EFAULT;
+		return 0;
+	case RNDADDTOENTCNT:
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+		if (get_user(ent_count_bits, p))
+			return -EFAULT;
+		ent_count_bits = (int)lrng_avail_entropy() + ent_count_bits;
+		if (ent_count_bits < 0)
+			ent_count_bits = 0;
+		if (ent_count_bits > LRNG_POOL_SIZE_BITS)
+			ent_count_bits = LRNG_POOL_SIZE_BITS;
+		lrng_pool_set_entropy(ent_count_bits);
+		return 0;
+	case RNDADDENTROPY:
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+		if (get_user(ent_count_bits, p++))
+			return -EFAULT;
+		if (ent_count_bits < 0)
+			return -EINVAL;
+		if (get_user(size, p++))
+			return -EFAULT;
+		if (size < 0)
+			return -EINVAL;
+		lrng_state_exseed_set(lrng_noise_source_user, false);
+		/* there cannot be more entropy than data */
+		ent_count_bits = min(ent_count_bits, size<<3);
+		return lrng_drng_write_common((const char __user *)p, size,
+					      ent_count_bits);
+	case RNDZAPENTCNT:
+	case RNDCLEARPOOL:
+		/* Clear the entropy pool counter. */
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+		lrng_pool_set_entropy(0);
+		return 0;
+	case RNDRESEEDCRNG:
+		/*
+		 * We leave the capability check here since it is present
+		 * in the upstream's RNG implementation. Yet, user space
+		 * can trigger a reseed as easy as writing into /dev/random
+		 * or /dev/urandom where no privilege is needed.
+		 */
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+		/* Force a reseed of all DRNGs */
+		lrng_drng_force_reseed();
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
+static int lrng_fasync(int fd, struct file *filp, int on)
+{
+	return fasync_helper(fd, filp, on, &fasync);
+}
+
+const struct file_operations random_fops = {
+	.read  = lrng_drng_read_block,
+	.write = lrng_drng_write,
+	.poll  = lrng_random_poll,
+	.unlocked_ioctl = lrng_ioctl,
+	.compat_ioctl = compat_ptr_ioctl,
+	.fasync = lrng_fasync,
+	.llseek = noop_llseek,
+};
+
+const struct file_operations urandom_fops = {
+	.read  = lrng_drng_read,
+	.write = lrng_drng_write,
+	.unlocked_ioctl = lrng_ioctl,
+	.compat_ioctl = compat_ptr_ioctl,
+	.fasync = lrng_fasync,
+	.llseek = noop_llseek,
+};
+
+SYSCALL_DEFINE3(getrandom, char __user *, buf, size_t, count,
+		unsigned int, flags)
+{
+	if (flags & ~(GRND_NONBLOCK|GRND_RANDOM|GRND_INSECURE))
+		return -EINVAL;
+
+	/*
+	 * Requesting insecure and blocking randomness at the same time makes
+	 * no sense.
+	 */
+	if ((flags &
+	     (GRND_INSECURE|GRND_RANDOM)) == (GRND_INSECURE|GRND_RANDOM))
+		return -EINVAL;
+
+	if (count > INT_MAX)
+		count = INT_MAX;
+
+	if (flags & GRND_INSECURE)
+		return lrng_drng_read(NULL, buf, count, NULL);
+
+	return lrng_read_common_block(flags & GRND_NONBLOCK, buf, count);
+}
diff --git a/drivers/char/lrng/lrng_internal.h b/drivers/char/lrng/lrng_internal.h
new file mode 100644
index 000000000000..c9a7bccd14a0
--- /dev/null
+++ b/drivers/char/lrng/lrng_internal.h
@@ -0,0 +1,296 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
+/*
+ * Copyright (C) 2018 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#ifndef _LRNG_INTERNAL_H
+#define _LRNG_INTERNAL_H
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+
+/*************************** General LRNG parameter ***************************/
+
+/* Entropy pool parameter
+ *
+ * The LRNG_POOL_SIZE cannot be smaller than 64 bytes as the SHA-1 operation
+ * in lrng_chacha20.c requires multiples of 64 bytes
+ */
+#define LRNG_POOL_SIZE			(16 << CONFIG_LRNG_POOL_SIZE)
+#define LRNG_POOL_WORD_BYTES		(4)	/* (sizeof(atomic_t)) */
+#define LRNG_POOL_SIZE_BYTES		(LRNG_POOL_SIZE * LRNG_POOL_WORD_BYTES)
+#define LRNG_POOL_SIZE_BITS		(LRNG_POOL_SIZE_BYTES * 8)
+#define LRNG_POOL_WORD_BITS		(LRNG_POOL_WORD_BYTES * 8)
+
+/* Security strength of LRNG -- this must match DRNG security strength */
+#define LRNG_DRNG_SECURITY_STRENGTH_BYTES 32
+#define LRNG_DRNG_SECURITY_STRENGTH_BITS (LRNG_DRNG_SECURITY_STRENGTH_BYTES * 8)
+#define LRNG_DRNG_BLOCKSIZE 64		/* Maximum of DRNG block sizes */
+
+/*
+ * SP800-90A defines a maximum request size of 1<<16 bytes. The given value is
+ * considered a safer margin.
+ *
+ * This value is allowed to be changed.
+ */
+#define LRNG_DRNG_MAX_REQSIZE		(1<<12)
+
+/*
+ * SP800-90A defines a maximum number of requests between reseeds of 2^48.
+ * The given value is considered a much safer margin, balancing requests for
+ * frequent reseeds with the need to conserve entropy. This value MUST NOT be
+ * larger than INT_MAX because it is used in an atomic_t.
+ *
+ * This value is allowed to be changed.
+ */
+#define LRNG_DRNG_RESEED_THRESH		(1<<20)
+
+/*
+ * Number of interrupts to be recorded to assume that DRNG security strength
+ * bits of entropy are received.
+ * Note: a value below the DRNG security strength should not be defined as this
+ *	 may imply the DRNG can never be fully seeded in case other noise
+ *	 sources are unavailable.
+ *
+ * This value is allowed to be changed.
+ */
+#define LRNG_IRQ_ENTROPY_BITS		LRNG_DRNG_SECURITY_STRENGTH_BITS
+
+/*
+ * Min required seed entropy is 128 bits covering the minimum entropy
+ * requirement of SP800-131A and the German BSI's TR02102.
+ *
+ * This value is allowed to be changed.
+ */
+#define LRNG_FULL_SEED_ENTROPY_BITS	LRNG_DRNG_SECURITY_STRENGTH_BITS
+#define LRNG_MIN_SEED_ENTROPY_BITS	128
+#define LRNG_INIT_ENTROPY_BITS		32
+
+/*
+ * Amount of entropy that is lost with the conditioning functions of LFSR and
+ * hash_df as shown with the entropy analysis compliant to SP800-90B.
+ */
+#define LRNG_CONDITIONING_ENTROPY_LOSS	1
+
+/*
+ * Wakeup value
+ *
+ * This value is allowed to be changed.
+ */
+#if (LRNG_POOL_SIZE_BITS <= (LRNG_DRNG_SECURITY_STRENGTH_BITS * 2))
+# define LRNG_WRITE_WAKEUP_ENTROPY	(LRNG_DRNG_SECURITY_STRENGTH_BITS + \
+					LRNG_CONDITIONING_ENTROPY_LOSS)
+#else
+# define LRNG_WRITE_WAKEUP_ENTROPY	(LRNG_DRNG_SECURITY_STRENGTH_BITS * 2)
+#endif
+
+/*
+ * Oversampling factor of IRQ events to obtain
+ * LRNG_DRNG_SECURITY_STRENGTH_BYTES. This factor is used when a
+ * high-resolution time stamp is not available. In this case, jiffies and
+ * register contents are used to fill the entropy pool. These noise sources
+ * are much less entropic than the high-resolution timer. The entropy content
+ * is the entropy content assumed with LRNG_IRQ_ENTROPY_BITS divided by
+ * LRNG_IRQ_OVERSAMPLING_FACTOR.
+ *
+ * This value is allowed to be changed.
+ */
+#define LRNG_IRQ_OVERSAMPLING_FACTOR	10
+
+/*
+ * Alignmask which should cover all cipher implementations
+ * WARNING: If this is changed to a value larger than 8, manual
+ * alignment is necessary as older versions of GCC may not be capable
+ * of aligning stack variables at boundaries greater than 8.
+ * In this case, PTR_ALIGN must be used.
+ */
+#define LRNG_KCAPI_ALIGN		8
+
+/************************ Default DRNG implementation *************************/
+
+extern struct chacha20_state chacha20;
+extern const struct lrng_crypto_cb lrng_cc20_crypto_cb;
+void lrng_cc20_init_state(struct chacha20_state *state);
+
+/********************************** /proc *************************************/
+
+static inline void lrng_pool_inc_numa_node(void) { }
+
+/****************************** LRNG interfaces *******************************/
+
+extern u32 lrng_write_wakeup_bits;
+extern int lrng_drng_reseed_max_time;
+
+void lrng_writer_wakeup(void);
+void lrng_init_wakeup(void);
+void lrng_debug_report_seedlevel(const char *name);
+void lrng_process_ready_list(void);
+
+/************************** Entropy pool management ***************************/
+
+enum lrng_external_noise_source {
+	lrng_noise_source_hw,
+	lrng_noise_source_user
+};
+
+bool lrng_state_exseed_allow(enum lrng_external_noise_source source);
+void lrng_state_exseed_set(enum lrng_external_noise_source source, bool type);
+void lrng_state_init_seed_work(void);
+u32 lrng_avail_entropy(void);
+void lrng_set_entropy_thresh(u32 new);
+int lrng_pool_trylock(void);
+void lrng_pool_unlock(void);
+void lrng_reset_state(void);
+void lrng_pool_all_numa_nodes_seeded(void);
+bool lrng_state_min_seeded(void);
+bool lrng_state_fully_seeded(void);
+bool lrng_state_operational(void);
+bool lrng_pool_highres_timer(void);
+void lrng_pool_set_entropy(u32 entropy_bits);
+void lrng_pool_lfsr(const u8 *buf, u32 buflen);
+void lrng_pool_lfsr_nonaligned(const u8 *buf, u32 buflen);
+void lrng_pool_lfsr_u32(u32 value);
+void lrng_pool_add_irq(u32 irq_num);
+void lrng_pool_add_entropy(u32 entropy_bits);
+
+struct entropy_buf {
+	u8 a[LRNG_DRNG_SECURITY_STRENGTH_BYTES];
+	u8 b[LRNG_DRNG_SECURITY_STRENGTH_BYTES];
+	u8 c[LRNG_DRNG_SECURITY_STRENGTH_BYTES];
+	u32 now;
+};
+
+int lrng_fill_seed_buffer(const struct lrng_crypto_cb *crypto_cb, void *hash,
+			  struct entropy_buf *entropy_buf, u32 entropy_retain);
+void lrng_init_ops(u32 seed_bits);
+
+/************************** Jitter RNG Noise Source ***************************/
+
+#ifdef CONFIG_LRNG_JENT
+u32 lrng_get_jent(u8 *outbuf, unsigned int outbuflen);
+u32 lrng_jent_entropylevel(void);
+#else /* CONFIG_CRYPTO_JITTERENTROPY */
+static inline u32 lrng_get_jent(u8 *outbuf, unsigned int outbuflen) {return 0; }
+static inline u32 lrng_jent_entropylevel(void) { return 0; }
+#endif /* CONFIG_CRYPTO_JITTERENTROPY */
+
+/*************************** CPU-based Noise Source ***************************/
+
+u32 lrng_get_arch(u8 *outbuf);
+u32 lrng_slow_noise_req_entropy(u32 required_entropy_bits);
+
+/****************************** DRNG processing *******************************/
+
+/* Secondary DRNG state handle */
+struct lrng_drng {
+	void *drng;				/* DRNG handle */
+	void *hash;				/* Hash handle */
+	const struct lrng_crypto_cb *crypto_cb;	/* Crypto callbacks */
+	atomic_t requests;			/* Number of DRNG requests */
+	unsigned long last_seeded;		/* Last time it was seeded */
+	bool fully_seeded;			/* Is DRNG fully seeded? */
+	bool force_reseed;			/* Force a reseed */
+	struct mutex lock;
+	spinlock_t spin_lock;
+};
+
+extern struct mutex lrng_crypto_cb_update;
+
+struct lrng_drng *lrng_drng_init_instance(void);
+struct lrng_drng *lrng_drng_atomic_instance(void);
+
+static __always_inline bool lrng_drng_is_atomic(struct lrng_drng *drng)
+{
+	return (drng->drng == lrng_drng_atomic_instance()->drng);
+}
+
+/* Lock the DRNG */
+static __always_inline void lrng_drng_lock(struct lrng_drng *drng,
+					   unsigned long *flags)
+{
+	/* Use spin lock in case the atomic DRNG context is used */
+	if (lrng_drng_is_atomic(drng)) {
+		spin_lock_irqsave(&drng->spin_lock, *flags);
+
+		/*
+		 * In case a lock transition happened while we were spinning,
+		 * catch this case and use the new lock type.
+		 */
+		if (unlikely(!lrng_drng_is_atomic(drng))) {
+			spin_unlock_irqrestore(&drng->spin_lock, *flags);
+			mutex_lock(&drng->lock);
+		}
+	} else {
+		mutex_lock(&drng->lock);
+	}
+}
+
+/* Unlock the DRNG */
+static __always_inline void lrng_drng_unlock(struct lrng_drng *drng,
+					     unsigned long *flags)
+{
+	if (lrng_drng_is_atomic(drng))
+		spin_unlock_irqrestore(&drng->spin_lock, *flags);
+	else
+		mutex_unlock(&drng->lock);
+}
+
+bool lrng_get_available(void);
+void lrng_set_available(void);
+void lrng_drngs_init_cc20(void);
+void lrng_drng_reset(struct lrng_drng *drng);
+int lrng_drng_get_atomic(u8 *outbuf, u32 outbuflen);
+int lrng_drng_get_sleep(u8 *outbuf, u32 outbuflen);
+void lrng_drng_force_reseed(void);
+void lrng_drng_seed_work(struct work_struct *dummy);
+
+static inline struct lrng_drng **lrng_drng_instances(void) { return NULL; }
+static inline void lrng_drngs_numa_alloc(void) { return; }
+
+/************************** Health Test linking code **************************/
+
+enum lrng_health_res {
+	lrng_health_pass,		/* Health test passes on time stamp */
+	lrng_health_fail_use,		/* Time stamp unhealthy, but mix in */
+	lrng_health_fail_drop		/* Time stamp unhealthy, drop it */
+};
+
+#ifdef CONFIG_LRNG_HEALTH_TESTS
+bool lrng_sp80090b_startup_complete(void);
+bool lrng_sp80090b_compliant(void);
+
+enum lrng_health_res lrng_health_test(u32 now_time);
+void lrng_health_disable(void);
+
+void lrng_reset(void);
+#else	/* CONFIG_LRNG_HEALTH_TESTS */
+static inline bool lrng_sp80090b_startup_complete(void) { return true; }
+static inline bool lrng_sp80090b_compliant(void) { return false; }
+
+static inline enum lrng_health_res
+lrng_health_test(u32 now_time) { return lrng_health_pass; }
+static inline void lrng_health_disable(void) { }
+#endif	/* CONFIG_LRNG_HEALTH_TESTS */
+
+/****************************** Helper code ***********************************/
+
+static inline u32 atomic_read_u32(atomic_t *v)
+{
+	return (u32)atomic_read(v);
+}
+
+/*************************** Auxiliary functions ******************************/
+
+void invalidate_batched_entropy(void);
+
+/***************************** Testing code ***********************************/
+
+#ifdef CONFIG_LRNG_TESTING
+bool lrng_raw_entropy_store(u32 value);
+#else	/* CONFIG_LRNG_TESTING */
+static inline bool lrng_raw_entropy_store(u32 value) { return false; }
+#endif	/* CONFIG_LRNG_TESTING */
+
+#endif /* _LRNG_INTERNAL_H */
diff --git a/drivers/char/lrng/lrng_lfsr.h b/drivers/char/lrng/lrng_lfsr.h
new file mode 100644
index 000000000000..f0e38a0aadfd
--- /dev/null
+++ b/drivers/char/lrng/lrng_lfsr.h
@@ -0,0 +1,152 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
+/*
+ * LRNG Linear Feedback Shift Register
+ *
+ * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+/* Status information about IRQ noise source */
+struct lrng_irq_info {
+	atomic_t num_events;	/* Number of healthy IRQs since last read */
+	atomic_t num_events_thresh;	/* Reseed threshold */
+	atomic_t reseed_in_progress;	/* Flag for on executing reseed */
+	bool irq_highres_timer;	/* Is high-resolution timer available? */
+	u32 irq_entropy_bits;	/* LRNG_IRQ_ENTROPY_BITS? */
+};
+
+/*
+ * This is the entropy pool used by the slow noise source. Its size should
+ * be at least as large as LRNG_DRNG_SECURITY_STRENGTH_BITS.
+ *
+ * The pool array is aligned to 8 bytes to comfort the kernel crypto API cipher
+ * implementations of the hash functions used to read the pool: for some
+ * accelerated implementations, we need an alignment to avoid a realignment
+ * which involves memcpy(). The alignment to 8 bytes should satisfy all crypto
+ * implementations.
+ *
+ * LRNG_POOL_SIZE is allowed to be changed only if the taps of the polynomial
+ * used for the LFSR are changed as well. The size must be in powers of 2 due
+ * to the mask handling in lrng_pool_lfsr_u32 which uses AND instead of modulo.
+ */
+struct lrng_pool {
+	union {
+		struct {
+			/*
+			 * hash_df implementation: counter, requested_bits and
+			 * pool form a linear buffer that is used in the
+			 * hash_df function specified in SP800-90A section
+			 * 10.3.1
+			 */
+			unsigned char counter;
+			__be32 requested_bits;
+
+			/* Pool */
+			atomic_t pool[LRNG_POOL_SIZE];
+			/* Ptr into pool for next IRQ word injection */
+			atomic_t pool_ptr;
+			/* rotate for LFSR */
+			atomic_t input_rotate;
+			/* All NUMA DRNGs seeded? */
+			bool all_online_numa_node_seeded;
+			/* IRQ noise source status info */
+			struct lrng_irq_info irq_info;
+			/* Serialize read of entropy pool */
+			spinlock_t lock;
+		};
+		/*
+		 * Static SHA-1 implementation in lrng_cc20_hash_buffer
+		 * processes data 64-byte-wise. Hence, ensure proper size
+		 * of LRNG entropy pool data structure.
+		 */
+		u8 hash_input_buf[LRNG_POOL_SIZE_BYTES + 64];
+	};
+};
+
+/*
+ * Implement a (modified) twisted Generalized Feedback Shift Register. (See M.
+ * Matsumoto & Y. Kurita, 1992.  Twisted GFSR generators. ACM Transactions on
+ * Modeling and Computer Simulation 2(3):179-194.  Also see M. Matsumoto & Y.
+ * Kurita, 1994.  Twisted GFSR generators II.  ACM Transactions on Modeling and
+ * Computer Simulation 4:254-266).
+ */
+static u32 const lrng_twist_table[8] = {
+	0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158,
+	0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 };
+
+/*
+ * The polynomials for the LFSR are taken from the document "Table of Linear
+ * Feedback Shift Registers" by Roy Ward, Tim Molteno, October 26, 2007.
+ * The first polynomial is from "Primitive Binary Polynomials" by Wayne
+ * Stahnke (1973) and is primitive as well as irreducible.
+ *
+ * Note, the tap values are smaller by one compared to the documentation because
+ * they are used as an index into an array where the index starts by zero.
+ *
+ * All polynomials were also checked to be primitive and irreducible with magma
+ * which ensures that the key property of the LFSR providing a compression
+ * function for entropy is guaranteed.
+ */
+static u32 const lrng_lfsr_polynomial[][4] = {
+	{ 15, 13, 12, 10 },			/* 16 words */
+	{ 31, 29, 25, 24 },			/* 32 words */
+	{ 63, 62, 60, 59 },			/* 64 words */
+	{ 127, 28, 26, 1 },			/* 128 words by Stahnke */
+	{ 255, 253, 250, 245 },			/* 256 words */
+	{ 511, 509, 506, 503 },			/* 512 words */
+	{ 1023, 1014, 1001, 1000 },		/* 1024 words */
+	{ 2047, 2034, 2033, 2028 },		/* 2048 words */
+	{ 4095, 4094, 4080, 4068 },		/* 4096 words */
+};
+
+static inline void _lrng_pool_lfsr_u32(struct lrng_pool *pool, u32 value)
+{
+	/*
+	 * Process the LFSR by altering not adjacent words but rather
+	 * more spaced apart words. Using a prime number ensures that all words
+	 * are processed evenly. As some the LFSR polynomials taps are close
+	 * together, processing adjacent words with the LSFR taps may be
+	 * inappropriate as the data just mixed-in at these taps may be not
+	 * independent from the current data to be mixed in.
+	 */
+	u32 ptr = (u32)atomic_add_return_relaxed(67, &pool->pool_ptr) &
+							(LRNG_POOL_SIZE - 1);
+	/*
+	 * Add 7 bits of rotation to the pool. At the beginning of the
+	 * pool, add an extra 7 bits rotation, so that successive passes
+	 * spread the input bits across the pool evenly.
+	 *
+	 * Note, there is a race between getting ptr and calculating
+	 * input_rotate when ptr is is obtained on two or more CPUs at the
+	 * same time. This race is irrelevant as it may only come into effect
+	 * if 3 or more CPUs race at the same time which is very unlikely. If
+	 * the race happens, it applies to one event only. As this rolling
+	 * supports the LFSR without being strictly needed, we accept this
+	 * race.
+	 */
+	u32 input_rotate = (u32)atomic_add_return_relaxed((ptr ? 7 : 14),
+					&pool->input_rotate) & 31;
+	u32 word = rol32(value, input_rotate);
+
+	BUILD_BUG_ON(LRNG_POOL_WORD_BYTES != sizeof(pool->pool[0]));
+	BUILD_BUG_ON(LRNG_POOL_SIZE - 1 !=
+		     lrng_lfsr_polynomial[CONFIG_LRNG_POOL_SIZE][0]);
+	word ^= atomic_read_u32(&pool->pool[ptr]);
+	word ^= atomic_read_u32(&pool->pool[
+		(ptr + lrng_lfsr_polynomial[CONFIG_LRNG_POOL_SIZE][0]) &
+		       (LRNG_POOL_SIZE - 1)]);
+	word ^= atomic_read_u32(&pool->pool[
+		(ptr + lrng_lfsr_polynomial[CONFIG_LRNG_POOL_SIZE][1]) &
+		       (LRNG_POOL_SIZE - 1)]);
+	word ^= atomic_read_u32(&pool->pool[
+		(ptr + lrng_lfsr_polynomial[CONFIG_LRNG_POOL_SIZE][2]) &
+		       (LRNG_POOL_SIZE - 1)]);
+	word ^= atomic_read_u32(&pool->pool[
+		(ptr + lrng_lfsr_polynomial[CONFIG_LRNG_POOL_SIZE][3]) &
+		       (LRNG_POOL_SIZE - 1)]);
+
+	word = (word >> 3) ^ lrng_twist_table[word & 7];
+	atomic_set(&pool->pool[ptr], word);
+}
+
+u32 __lrng_pool_hash_df(const struct lrng_crypto_cb *crypto_cb, void *hash,
+			struct lrng_pool *pool, u8 *outbuf, u32 requested_bits);
diff --git a/drivers/char/lrng/lrng_pool.c b/drivers/char/lrng/lrng_pool.c
new file mode 100644
index 000000000000..1547aa14dbc6
--- /dev/null
+++ b/drivers/char/lrng/lrng_pool.c
@@ -0,0 +1,585 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG Entropy pool management
+ *
+ * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <asm/irq_regs.h>
+#include <linux/lrng.h>
+#include <linux/percpu.h>
+#include <linux/random.h>
+#include <linux/utsname.h>
+#include <linux/workqueue.h>
+
+#include "lrng_internal.h"
+#include "lrng_lfsr.h"
+
+struct lrng_state {
+	bool lrng_operational;		/* Is DRNG operational? */
+	bool lrng_fully_seeded;		/* Is DRNG fully seeded? */
+	bool lrng_min_seeded;		/* Is DRNG minimally seeded? */
+
+	/*
+	 * To ensure that external entropy providers cannot dominate the
+	 * internal noise sources but yet cannot be dominated by internal
+	 * noise sources, the following booleans are intended to allow
+	 * external to provide seed once when a DRNG reseed occurs. This
+	 * triggering of external noise source is performed even when the
+	 * entropy pool has sufficient entropy.
+	 */
+	bool lrng_seed_hw;		/* Allow HW to provide seed */
+	bool lrng_seed_user;		/* Allow user space to provide seed */
+
+	struct work_struct lrng_seed_work;	/* (re)seed work queue */
+};
+
+static struct lrng_pool lrng_pool __aligned(LRNG_KCAPI_ALIGN) = {
+	.irq_info	= {
+		.irq_entropy_bits	= LRNG_IRQ_ENTROPY_BITS,
+		.num_events_thresh	= ATOMIC_INIT(LRNG_INIT_ENTROPY_BITS +
+						LRNG_CONDITIONING_ENTROPY_LOSS),
+		/* Sample IRQ pointer data at least during boot */
+		.irq_highres_timer	= false },
+	.lock		= __SPIN_LOCK_UNLOCKED(lrng_pool.lock)
+};
+
+static struct lrng_state lrng_state = { false, false, false, true, true };
+
+/********************************** Helper ***********************************/
+
+/* External entropy provider is allowed to provide seed data */
+bool lrng_state_exseed_allow(enum lrng_external_noise_source source)
+{
+	if (source == lrng_noise_source_hw)
+		return lrng_state.lrng_seed_hw;
+	return lrng_state.lrng_seed_user;
+}
+
+/* Enable / disable external entropy provider to furnish seed */
+void lrng_state_exseed_set(enum lrng_external_noise_source source, bool type)
+{
+	if (source == lrng_noise_source_hw)
+		lrng_state.lrng_seed_hw = type;
+	else
+		lrng_state.lrng_seed_user = type;
+}
+
+static inline void lrng_state_exseed_allow_all(void)
+{
+	lrng_state_exseed_set(lrng_noise_source_hw, true);
+	lrng_state_exseed_set(lrng_noise_source_user, true);
+}
+
+void lrng_state_init_seed_work(void)
+{
+	INIT_WORK(&lrng_state.lrng_seed_work, lrng_drng_seed_work);
+}
+
+static inline u32 lrng_entropy_to_data(u32 entropy_bits)
+{
+	return ((entropy_bits * lrng_pool.irq_info.irq_entropy_bits) /
+		LRNG_DRNG_SECURITY_STRENGTH_BITS);
+}
+
+static inline u32 lrng_data_to_entropy(u32 irqnum)
+{
+	return ((irqnum * LRNG_DRNG_SECURITY_STRENGTH_BITS) /
+		lrng_pool.irq_info.irq_entropy_bits);
+}
+
+u32 lrng_avail_entropy(void)
+{
+	return min_t(u32, LRNG_POOL_SIZE_BITS, lrng_data_to_entropy(
+			atomic_read_u32(&lrng_pool.irq_info.num_events)));
+}
+
+void lrng_set_entropy_thresh(u32 new)
+{
+	atomic_set(&lrng_pool.irq_info.num_events_thresh,
+		   lrng_entropy_to_data(new));
+}
+
+/*
+ * Reading of the LRNG pool is only allowed by one caller. The reading is
+ * only performed to (re)seed DRNGs. Thus, if this "lock" is already taken,
+ * the reseeding operation is in progress. The caller is not intended to wait
+ * but continue with its other operation.
+ */
+int lrng_pool_trylock(void)
+{
+	return atomic_cmpxchg(&lrng_pool.irq_info.reseed_in_progress, 0, 1);
+}
+
+void lrng_pool_unlock(void)
+{
+	atomic_set(&lrng_pool.irq_info.reseed_in_progress, 0);
+}
+
+void lrng_reset_state(void)
+{
+	struct lrng_irq_info *irq_info = &lrng_pool.irq_info;
+
+	atomic_set(&irq_info->num_events, 0);
+	lrng_state.lrng_operational = false;
+	lrng_state.lrng_fully_seeded = false;
+	lrng_state.lrng_min_seeded = false;
+	lrng_pool.all_online_numa_node_seeded = false;
+	pr_debug("reset LRNG\n");
+}
+
+void lrng_pool_all_numa_nodes_seeded(void)
+{
+	lrng_pool.all_online_numa_node_seeded = true;
+}
+
+bool lrng_state_min_seeded(void)
+{
+	return lrng_state.lrng_min_seeded;
+}
+
+bool lrng_state_fully_seeded(void)
+{
+	return lrng_state.lrng_fully_seeded;
+}
+
+bool lrng_state_operational(void)
+{
+	return lrng_state.lrng_operational;
+}
+
+bool lrng_pool_highres_timer(void)
+{
+	return lrng_pool.irq_info.irq_highres_timer;
+}
+
+void lrng_pool_set_entropy(u32 entropy_bits)
+{
+	atomic_set(&lrng_pool.irq_info.num_events,
+		   lrng_entropy_to_data(entropy_bits));
+}
+
+static void lrng_pool_configure(bool highres_timer, u32 irq_entropy_bits)
+{
+	struct lrng_irq_info *irq_info = &lrng_pool.irq_info;
+
+	irq_info->irq_highres_timer = highres_timer;
+	if (irq_info->irq_entropy_bits != irq_entropy_bits) {
+		irq_info->irq_entropy_bits = irq_entropy_bits;
+		/* Reset the threshold based on new oversampling factor. */
+		lrng_set_entropy_thresh(atomic_read_u32(
+						&irq_info->num_events_thresh));
+	}
+}
+
+static int __init lrng_init_time_source(void)
+{
+	if (random_get_entropy() || random_get_entropy()) {
+		/*
+		 * As the highres timer is identified here, previous interrupts
+		 * obtained during boot time are treated like a lowres-timer
+		 * would have been present.
+		 */
+		lrng_pool_configure(true, LRNG_IRQ_ENTROPY_BITS);
+	} else {
+		lrng_health_disable();
+		lrng_pool_configure(false, LRNG_IRQ_ENTROPY_BITS *
+					   LRNG_IRQ_OVERSAMPLING_FACTOR);
+		pr_warn("operating without high-resolution timer and applying "
+			"IRQ oversampling factor %u\n",
+			LRNG_IRQ_OVERSAMPLING_FACTOR);
+	}
+
+	return 0;
+}
+
+core_initcall(lrng_init_time_source);
+
+/* invoke function with buffer aligned to 4 bytes */
+void lrng_pool_lfsr(const u8 *buf, u32 buflen)
+{
+	u32 *p_buf = (u32 *)buf;
+
+	for (; buflen >= 4; buflen -= 4)
+		lrng_pool_lfsr_u32(*p_buf++);
+
+	buf = (u8 *)p_buf;
+	while (buflen--)
+		lrng_pool_lfsr_u32(*buf++);
+}
+
+void lrng_pool_lfsr_nonaligned(const u8 *buf, u32 buflen)
+{
+	while (buflen) {
+		if (!((unsigned long)buf & (sizeof(u32) - 1))) {
+			lrng_pool_lfsr(buf, buflen);
+			return;
+		}
+
+		lrng_pool_lfsr_u32(*buf++);
+		buflen--;
+	}
+}
+
+/**************************** Interrupt processing ****************************/
+
+/**
+ * Hot code path - inject data into entropy pool using LFSR
+ */
+void lrng_pool_lfsr_u32(u32 value)
+{
+	_lrng_pool_lfsr_u32(&lrng_pool, value);
+}
+
+/**
+ * Hot code path - mix data into entropy pool
+ */
+void lrng_pool_add_irq(u32 irq_num)
+{
+	struct lrng_irq_info *irq_info = &lrng_pool.irq_info;
+
+	atomic_add(irq_num, &irq_info->num_events);
+
+	/*
+	 * Once all DRNGs are fully seeded, the interrupt noise
+	 * sources will not trigger any reseeding any more.
+	 */
+	if (likely(lrng_pool.all_online_numa_node_seeded))
+		return;
+
+	/* Only try to reseed if the DRNG is alive. */
+	if (!lrng_get_available())
+		return;
+
+	/* Only trigger the DRNG reseed if we have collected enough IRQs. */
+	if (atomic_read_u32(&lrng_pool.irq_info.num_events) <
+	    atomic_read_u32(&lrng_pool.irq_info.num_events_thresh))
+		return;
+
+	/* Ensure that the seeding only occurs once at any given time. */
+	if (lrng_pool_trylock())
+		return;
+
+	/* Seed the DRNG with IRQ noise. */
+	schedule_work(&lrng_state.lrng_seed_work);
+}
+
+void lrng_pool_add_entropy(u32 entropy_bits)
+{
+	lrng_pool_add_irq(lrng_entropy_to_data(entropy_bits));
+}
+
+/**
+ * Generate a hashed output of pool using the SP800-90A section 10.3.1 hash_df
+ * function
+ */
+u32 __lrng_pool_hash_df(const struct lrng_crypto_cb *crypto_cb, void *hash,
+			struct lrng_pool *pool, u8 *outbuf, u32 requested_bits)
+{
+	u32 digestsize, requested_bytes = requested_bits >> 3,
+	    generated_bytes = 0;
+	u8 digest[64] __aligned(LRNG_KCAPI_ALIGN);
+
+	digestsize = crypto_cb->lrng_hash_digestsize(hash);
+	if (digestsize > sizeof(digest)) {
+		pr_err("Digest buffer too small\n");
+		return 0;
+	}
+
+	pool->counter = 1;
+	pool->requested_bits = cpu_to_be32(requested_bytes << 3);
+
+	while (requested_bytes) {
+		u32 tocopy = min_t(u32, requested_bytes, digestsize);
+
+		/* The counter must not wrap */
+		if (pool->counter == 0)
+			goto out;
+
+		if (crypto_cb->lrng_hash_buffer(hash, (u8 *)pool,
+						LRNG_POOL_SIZE_BYTES + 64,
+						digest))
+			goto out;
+
+		/* Copy the data out to the caller */
+		memcpy(outbuf + generated_bytes, digest, tocopy);
+		requested_bytes -= tocopy;
+		generated_bytes += tocopy;
+		pool->counter++;
+	}
+
+out:
+	/* Mix read data back into pool for backtracking resistance */
+	if (generated_bytes)
+		lrng_pool_lfsr(outbuf, generated_bytes);
+	memzero_explicit(digest, digestsize);
+	return (generated_bytes<<3);
+}
+
+static inline u32 lrng_pool_hash_df(const struct lrng_crypto_cb *crypto_cb,
+				    void *hash, u8 *outbuf, u32 requested_bits)
+{
+	return __lrng_pool_hash_df(crypto_cb, hash, &lrng_pool, outbuf,
+				   requested_bits);
+}
+
+/**
+ * Read the entropy pool out for use.
+ *
+ * This function handles the translation from the number of received interrupts
+ * into an entropy statement. The conversion depends on LRNG_IRQ_ENTROPY_BITS
+ * which defines how many interrupts must be received to obtain 256 bits of
+ * entropy. With this value, the function lrng_data_to_entropy converts a given
+ * data size (received interrupts, requested amount of data, etc.) into an
+ * entropy statement. lrng_entropy_to_data does the reverse.
+ *
+ * Both functions are agnostic about the type of data: when the number of
+ * interrupts is processed by these functions, the resulting entropy value is in
+ * bits as we assume the entropy of interrupts is measured in bits. When data is
+ * processed, the entropy value is in bytes as the data is measured in bytes.
+ *
+ * @outbuf: buffer to store data in with size LRNG_DRNG_SECURITY_STRENGTH_BYTES
+ * @requested_entropy_bits: requested bits of entropy -- the function will
+ *			    return at least this amount of entropy if available
+ * @entropy_retain: amount of entropy in bits that should be left in the pool
+ * @return: estimated entropy from the IRQs that was obtained
+ */
+static u32 lrng_get_pool(const struct lrng_crypto_cb *crypto_cb, void *hash,
+			 u8 *outbuf, u32 requested_entropy_bits,
+			 u32 entropy_retain)
+{
+	struct lrng_pool *pool = &lrng_pool;
+	struct lrng_state *state = &lrng_state;
+	struct lrng_irq_info *irq_info = &pool->irq_info;
+	unsigned long flags;
+
+	u32 irq_num_events_used, irq_num_events, avail_entropy_bits;
+
+	/* This get_pool operation must only be called once at a given time! */
+	spin_lock_irqsave(&pool->lock, flags);
+
+	/* How many unused interrupts are in entropy pool? */
+	irq_num_events = atomic_read_u32(&irq_info->num_events);
+	/* Convert available interrupts into entropy statement */
+	avail_entropy_bits = lrng_data_to_entropy(irq_num_events);
+
+	/* Cap available entropy to pool size */
+	avail_entropy_bits =
+			min_t(u32, avail_entropy_bits, LRNG_POOL_SIZE_BITS);
+
+	/* How much entropy we need to and can we use? */
+	if (unlikely(!state->lrng_fully_seeded)) {
+		/*
+		 * During boot time, we read 256 bits data with
+		 * avail_entropy_bits entropy. In case our conservative
+		 * entropy estimate underestimates the available entropy
+		 * we can transport as much available entropy as
+		 * possible. The entropy pool does not operate compliant to
+		 * the German AIS 21/31 NTG.1 yet.
+		 */
+		requested_entropy_bits =
+				LRNG_DRNG_SECURITY_STRENGTH_BITS;
+	} else {
+		/* Provide all entropy above retaining level */
+		if (avail_entropy_bits < entropy_retain) {
+			requested_entropy_bits = 0;
+			goto out;
+		}
+		avail_entropy_bits -= entropy_retain;
+		requested_entropy_bits = min_t(u32, avail_entropy_bits,
+					       requested_entropy_bits);
+	}
+
+	/* Hash is a compression function: we generate entropy amount of data */
+	requested_entropy_bits = round_down(requested_entropy_bits, 8);
+
+	requested_entropy_bits = lrng_pool_hash_df(crypto_cb, hash, outbuf,
+						   requested_entropy_bits);
+
+	/* Boot time: After getting the full buffer adjust the entropy value. */
+	requested_entropy_bits = min_t(u32, avail_entropy_bits,
+				       requested_entropy_bits);
+
+out:
+	/* Convert used entropy into interrupt number for subtraction */
+	irq_num_events_used = lrng_entropy_to_data(requested_entropy_bits);
+
+	/*
+	 * The hash_df operation entropy assessment shows that the output
+	 * entropy is one bit smaller than the input entropy. Therefore we
+	 * account for this one bit of entropy here: if we have sufficient
+	 * entropy in the LFSR, we say we used one bit of entropy more.
+	 * Otherwise we reduce the amount of entropy we say we generated with
+	 * the hash_df.
+	 */
+	if (irq_num_events_used) {
+		if ((irq_num_events_used + LRNG_CONDITIONING_ENTROPY_LOSS) <=
+		    lrng_entropy_to_data(avail_entropy_bits)) {
+			irq_num_events_used += LRNG_CONDITIONING_ENTROPY_LOSS;
+		} else {
+			if (unlikely(requested_entropy_bits <
+				     LRNG_CONDITIONING_ENTROPY_LOSS))
+				requested_entropy_bits = 0;
+			else
+				requested_entropy_bits -=
+						LRNG_CONDITIONING_ENTROPY_LOSS;
+		}
+	}
+
+	/*
+	 * New events might have arrived in the meanwhile and we don't
+	 * want to throw them away unconditionally. On the other hand,
+	 * these new events might have been mixed in before
+	 * lrng_hash_df_pool() had been able to draw any entropy
+	 * from the pool and thus, the pool capacity might have been
+	 * exceeded at some point. Note that in theory, some events
+	 * might get lost inbetween the atomic_read() and
+	 * atomic_set() below. But that's fine, because it's no real
+	 * concern while code preventing this would come at the cost of
+	 * additional complexity. Likewise, some events which arrived
+	 * after full or partial completion of the __lrng_hash_df_pool()
+	 * above might get unnecessarily thrown away by the min()
+	 * operation below; the same argument applies there.
+	 */
+	irq_num_events = atomic_read_u32(&irq_info->num_events);
+	irq_num_events = min_t(u32, irq_num_events,
+			       lrng_entropy_to_data(LRNG_POOL_SIZE_BITS));
+	irq_num_events -= irq_num_events_used;
+	atomic_set(&irq_info->num_events, irq_num_events);
+
+	spin_unlock_irqrestore(&pool->lock, flags);
+
+	/* Obtain entropy statement in bits from the used entropy */
+	pr_debug("obtained %u bits of entropy from %u newly collected "
+		 "interrupts - not using %u interrupts\n",
+		 requested_entropy_bits, irq_num_events_used,
+		 irq_num_events);
+
+	return requested_entropy_bits;
+}
+
+/* Fill the seed buffer with data from the noise sources */
+int lrng_fill_seed_buffer(const struct lrng_crypto_cb *crypto_cb, void *hash,
+			  struct entropy_buf *entropy_buf, u32 entropy_retain)
+{
+	struct lrng_state *state = &lrng_state;
+	u32 total_entropy_bits = 0;
+
+	/* Require at least 128 bits of entropy for any reseed. */
+	if (state->lrng_fully_seeded &&
+	    (lrng_avail_entropy() <
+	     lrng_slow_noise_req_entropy(LRNG_MIN_SEED_ENTROPY_BITS +
+					 LRNG_CONDITIONING_ENTROPY_LOSS) +
+	      entropy_retain))
+		goto wakeup;
+
+	/*
+	 * Concatenate the output of the noise sources. This would be the
+	 * spot to add an entropy extractor logic if desired. Note, this
+	 * has the ability to collect entropy equal or larger than the DRNG
+	 * strength.
+	 */
+	total_entropy_bits = lrng_get_pool(crypto_cb, hash, entropy_buf->a,
+					   LRNG_DRNG_SECURITY_STRENGTH_BITS,
+					   entropy_retain);
+	total_entropy_bits += lrng_get_arch(entropy_buf->b);
+	total_entropy_bits += lrng_get_jent(entropy_buf->c,
+					    LRNG_DRNG_SECURITY_STRENGTH_BYTES);
+
+	/* also reseed the DRNG with the current time stamp */
+	entropy_buf->now = random_get_entropy();
+
+	/* allow external entropy provider to provide seed */
+	lrng_state_exseed_allow_all();
+
+wakeup:
+	/*
+	 * Shall we wake up user space writers? This location covers
+	 * ensures that the user space provider does not dominate the internal
+	 * noise sources since in case the first call of this function finds
+	 * sufficient entropy in the entropy pool, it will not trigger the
+	 * wakeup. This implies that when the next /dev/urandom read happens,
+	 * the entropy pool is drained.
+	 */
+	lrng_writer_wakeup();
+
+	return total_entropy_bits;
+}
+
+/**
+ * Set the slow noise source reseed trigger threshold. The initial threshold
+ * is set to the minimum data size that can be read from the pool: a word. Upon
+ * reaching this value, the next seed threshold of 128 bits is set followed
+ * by 256 bits.
+ *
+ * @entropy_bits: size of entropy currently injected into DRNG
+ */
+void lrng_init_ops(u32 seed_bits)
+{
+	struct lrng_state *state = &lrng_state;
+
+	if (state->lrng_operational)
+		return;
+
+	/* DRNG is seeded with full security strength */
+	if (state->lrng_fully_seeded) {
+		state->lrng_operational = lrng_sp80090b_startup_complete();
+		lrng_process_ready_list();
+		lrng_init_wakeup();
+	} else if (seed_bits >= LRNG_FULL_SEED_ENTROPY_BITS) {
+		invalidate_batched_entropy();
+		state->lrng_fully_seeded = true;
+		state->lrng_operational = lrng_sp80090b_startup_complete();
+		state->lrng_min_seeded = true;
+		pr_info("LRNG fully seeded with %u bits of entropy\n",
+			seed_bits);
+		lrng_set_entropy_thresh(LRNG_FULL_SEED_ENTROPY_BITS +
+					LRNG_CONDITIONING_ENTROPY_LOSS);
+		lrng_process_ready_list();
+		lrng_init_wakeup();
+
+	} else if (!state->lrng_min_seeded) {
+
+		/* DRNG is seeded with at least 128 bits of entropy */
+		if (seed_bits >= LRNG_MIN_SEED_ENTROPY_BITS) {
+			invalidate_batched_entropy();
+			state->lrng_min_seeded = true;
+			pr_info("LRNG minimally seeded with %u bits of "
+				"entropy\n", seed_bits);
+			lrng_set_entropy_thresh(
+				lrng_slow_noise_req_entropy(
+					LRNG_FULL_SEED_ENTROPY_BITS +
+					LRNG_CONDITIONING_ENTROPY_LOSS));
+			lrng_process_ready_list();
+			lrng_init_wakeup();
+
+		/* DRNG is seeded with at least LRNG_INIT_ENTROPY_BITS bits */
+		} else if (seed_bits >= LRNG_INIT_ENTROPY_BITS) {
+			pr_info("LRNG initial entropy level %u bits of "
+				"entropy\n", seed_bits);
+			lrng_set_entropy_thresh(
+				lrng_slow_noise_req_entropy(
+					LRNG_MIN_SEED_ENTROPY_BITS +
+					LRNG_CONDITIONING_ENTROPY_LOSS));
+		}
+	}
+}
+
+int __init rand_initialize(void)
+{
+	ktime_t now_time = ktime_get_real();
+	unsigned int i, rand;
+
+	lrng_pool_lfsr_u32(now_time);
+	for (i = 0; i < LRNG_POOL_SIZE; i++) {
+		if (!arch_get_random_seed_int(&rand) &&
+		    !arch_get_random_int(&rand))
+			rand = random_get_entropy();
+		lrng_pool_lfsr_u32(rand);
+	}
+	lrng_pool_lfsr_nonaligned((u8 *)utsname(), sizeof(*(utsname())));
+
+	return 0;
+}
diff --git a/drivers/char/lrng/lrng_sw_noise.c b/drivers/char/lrng/lrng_sw_noise.c
new file mode 100644
index 000000000000..d153371cb25b
--- /dev/null
+++ b/drivers/char/lrng/lrng_sw_noise.c
@@ -0,0 +1,102 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG Slow Noise Source: Interrupt data collection
+ *
+ * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#include <asm/irq_regs.h>
+#include <asm/ptrace.h>
+#include <linux/random.h>
+
+#include "lrng_internal.h"
+#include "lrng_sw_noise.h"
+
+/* Holder of time stamps before mixing them into the entropy pool */
+static DEFINE_PER_CPU(u32 [LRNG_TIME_ARRAY_SIZE], lrng_time);
+static DEFINE_PER_CPU(u32, lrng_time_ptr) = 0;
+static DEFINE_PER_CPU(u8, lrng_time_irqs) = 0;
+
+/**
+ * Batching up of entropy in per-CPU array before injecting into entropy pool.
+ */
+static inline void lrng_time_process(void)
+{
+	u32 i, ptr, now_time = random_get_entropy() &
+			       (likely(lrng_state_fully_seeded()) ?
+				LRNG_TIME_SLOTSIZE_MASK : (u32)-1);
+	enum lrng_health_res health_test;
+
+	/* Ensure sufficient space in lrng_time_irqs */
+	BUILD_BUG_ON(LRNG_TIME_NUM_VALUES >= (1 << (sizeof(u8) << 3)));
+	BUILD_BUG_ON(LRNG_TIME_ARRAY_MEMBER_BITS % LRNG_TIME_SLOTSIZE_BITS);
+	/* Ensure consistency of values */
+	BUILD_BUG_ON(LRNG_TIME_ARRAY_MEMBER_BITS != sizeof(lrng_time[0]) << 3);
+
+	if (lrng_raw_entropy_store(now_time))
+		return;
+
+	health_test = lrng_health_test(now_time);
+	if (health_test > lrng_health_fail_use)
+		return;
+
+	/* During boot time, we mix the full time stamp directly into LFSR */
+	if (unlikely(!lrng_state_fully_seeded())) {
+		lrng_pool_lfsr_u32(now_time);
+		if (health_test == lrng_health_pass)
+			lrng_pool_add_irq(1);
+		return;
+	}
+
+	ptr = this_cpu_inc_return(lrng_time_ptr) & LRNG_TIME_WORD_MASK;
+	this_cpu_or(lrng_time[lrng_time_idx2array(ptr)],
+		    lrng_time_slot_val(now_time & LRNG_TIME_SLOTSIZE_MASK,
+				       lrng_time_idx2slot(ptr)));
+
+	/* Interrupt delivers entropy if health test passes */
+	if (health_test == lrng_health_pass)
+		this_cpu_inc(lrng_time_irqs);
+
+	/* Only mix the buffer of time stamps into LFSR when wrapping */
+	if (ptr < LRNG_TIME_WORD_MASK)
+		return;
+
+	for (i = 0; i < LRNG_TIME_ARRAY_SIZE; i++) {
+		lrng_pool_lfsr_u32(this_cpu_read(lrng_time[i]));
+		this_cpu_write(lrng_time[i], 0);
+	}
+	lrng_pool_add_irq(this_cpu_read(lrng_time_irqs));
+	this_cpu_write(lrng_time_irqs, 0);
+}
+
+/**
+ * Hot code path - Callback for interrupt handler
+ */
+void add_interrupt_randomness(int irq, int irq_flags)
+{
+	lrng_time_process();
+
+	if (!lrng_pool_highres_timer()) {
+		struct pt_regs *regs = get_irq_regs();
+		static atomic_t reg_idx = ATOMIC_INIT(0);
+		u64 ip;
+
+		lrng_pool_lfsr_u32(jiffies);
+		lrng_pool_lfsr_u32(irq);
+		lrng_pool_lfsr_u32(irq_flags);
+
+		if (regs) {
+			u32 *ptr = (u32 *)regs;
+			int reg_ptr = atomic_add_return_relaxed(1, &reg_idx);
+			size_t n = (sizeof(struct pt_regs) / sizeof(u32));
+
+			ip = instruction_pointer(regs);
+			lrng_pool_lfsr_u32(*(ptr + (reg_ptr % n)));
+		} else
+			ip = _RET_IP_;
+
+		lrng_pool_lfsr_u32(ip >> 32);
+		lrng_pool_lfsr_u32(ip);
+	}
+}
+EXPORT_SYMBOL(add_interrupt_randomness);
diff --git a/drivers/char/lrng/lrng_sw_noise.h b/drivers/char/lrng/lrng_sw_noise.h
new file mode 100644
index 000000000000..107c6f9153bc
--- /dev/null
+++ b/drivers/char/lrng/lrng_sw_noise.h
@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
+/*
+ * LRNG Slow Noise Source: Time stamp array handling
+ *
+ * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+/*
+ * To limit the impact on the interrupt handling, the LRNG concatenates
+ * entropic LSB parts of the time stamps in a per-CPU array and only
+ * injects them into the entropy pool when the array is full.
+ */
+
+/* Store multiple integers in one u32 */
+#define LRNG_TIME_SLOTSIZE_BITS		(8)
+#define LRNG_TIME_SLOTSIZE_MASK		((1 << LRNG_TIME_SLOTSIZE_BITS) - 1)
+#define LRNG_TIME_ARRAY_MEMBER_BITS	(4 << 3)
+#define LRNG_TIME_SLOTS_PER_UINT	(LRNG_TIME_ARRAY_MEMBER_BITS / \
+					 LRNG_TIME_SLOTSIZE_BITS)
+
+/*
+ * Number of time values to store in the array - in small environments
+ * only one atomic_t variable per CPU is used.
+ */
+#define LRNG_TIME_NUM_VALUES		(CONFIG_BASE_SMALL ?		\
+					 LRNG_TIME_SLOTS_PER_UINT : 64)
+/* Mask of LSB of time stamp to store */
+#define LRNG_TIME_WORD_MASK		(LRNG_TIME_NUM_VALUES - 1)
+
+#define LRNG_TIME_SLOTS_MASK		(LRNG_TIME_SLOTS_PER_UINT - 1)
+#define LRNG_TIME_ARRAY_SIZE		(LRNG_TIME_NUM_VALUES /	\
+					 LRNG_TIME_SLOTS_PER_UINT)
+
+/* Starting bit index of slot */
+static inline unsigned int lrng_time_slot2bitindex(unsigned int slot)
+{
+	return (LRNG_TIME_SLOTSIZE_BITS * slot);
+}
+
+/* Convert index into the array index */
+static inline unsigned int lrng_time_idx2array(unsigned int idx)
+{
+	return idx / LRNG_TIME_SLOTS_PER_UINT;
+}
+
+/* Convert index into the slot of a given array index */
+static inline unsigned int lrng_time_idx2slot(unsigned int idx)
+{
+	return idx & LRNG_TIME_SLOTS_MASK;
+}
+
+/* Convert value into slot value */
+static inline unsigned int lrng_time_slot_val(unsigned int val,
+					      unsigned int slot)
+{
+	return val << lrng_time_slot2bitindex(slot);
+}
diff --git a/include/linux/lrng.h b/include/linux/lrng.h
new file mode 100644
index 000000000000..72abb575eb72
--- /dev/null
+++ b/include/linux/lrng.h
@@ -0,0 +1,71 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
+/*
+ * Copyright (C) 2018 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#ifndef _LRNG_H
+#define _LRNG_H
+
+#include <linux/errno.h>
+#include <linux/types.h>
+
+/**
+ * struct lrng_crypto_cb - cryptographic callback functions
+ * @lrng_drng_name		Name of DRNG
+ * @lrng_hash_name		Name of Hash used for reading entropy pool
+ * @lrng_drng_alloc:		Allocate DRNG -- the provided integer should be
+ *				used for sanity checks.
+ *				return: allocated data structure or PTR_ERR on
+ *					error
+ * @lrng_drng_dealloc:		Deallocate DRNG
+ * @lrng_drng_seed_helper:	Seed the DRNG with data of arbitrary length
+ *				drng: is pointer to data structure allocated
+ *				      with lrng_drng_alloc
+ *				return: >= 0 on success, < 0 on error
+ * @lrng_drng_generate_helper:	Generate random numbers from the DRNG with
+ *				arbitrary length
+ * @lrng_drng_generate_helper_full: Generate random numbers from the DRNG with
+ *				    arbitrary length where the output is
+ *				    capable of providing 1 bit of entropy per
+ *				    data bit.
+ *				    return: generated number of bytes,
+ *					    < 0 on error
+ * @lrng_hash_alloc:		Allocate the hash for reading the entropy pool
+ *				return: allocated data structure (NULL is
+ *					success too) or ERR_PTR on error
+ * @lrng_hash_dealloc:		Deallocate Hash
+ * @lrng_hash_digestsize:	Return the digestsize for the used hash to read
+ *				out entropy pool
+ *				hash: is pointer to data structure allocated
+ *				      with lrng_hash_alloc
+ *				return: size of digest of hash in bytes
+ * @lrng_hash_buffer:		Generate hash
+ *				hash: is pointer to data structure allocated
+ *				      with lrng_hash_alloc
+ *				return: 0 on success, < 0 on error
+ */
+struct lrng_crypto_cb {
+	const char *(*lrng_drng_name)(void);
+	const char *(*lrng_hash_name)(void);
+	void *(*lrng_drng_alloc)(u32 sec_strength);
+	void (*lrng_drng_dealloc)(void *drng);
+	int (*lrng_drng_seed_helper)(void *drng, const u8 *inbuf, u32 inbuflen);
+	int (*lrng_drng_generate_helper)(void *drng, u8 *outbuf, u32 outbuflen);
+	int (*lrng_drng_generate_helper_full)(void *drng, u8 *outbuf,
+					      u32 outbuflen);
+	void *(*lrng_hash_alloc)(const u8 *key, u32 keylen);
+	void (*lrng_hash_dealloc)(void *hash);
+	u32 (*lrng_hash_digestsize)(void *hash);
+	int (*lrng_hash_buffer)(void *hash, const u8 *inbuf, u32 inbuflen,
+				u8 *digest);
+};
+
+/* Register cryptographic backend */
+#ifdef CONFIG_LRNG_DRNG_SWITCH
+int lrng_set_drng_cb(const struct lrng_crypto_cb *cb);
+#else	/* CONFIG_LRNG_DRNG_SWITCH */
+static inline int
+lrng_set_drng_cb(const struct lrng_crypto_cb *cb) { return -EOPNOTSUPP; }
+#endif	/* CONFIG_LRNG_DRNG_SWITCH */
+
+#endif /* _LRNG_H */
-- 
2.24.1





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v27 02/12] LRNG - allocate one DRNG instance per NUMA node
  2020-01-09  8:29     ` [PATCH v27 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
  2020-01-09  8:30       ` [PATCH v27 01/12] Linux Random Number Generator Stephan Müller
@ 2020-01-09  8:31       ` Stephan Müller
  2020-01-09  8:31       ` [PATCH v27 03/12] LRNG - sysctls and /proc interface Stephan Müller
                         ` (10 subsequent siblings)
  12 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2020-01-09  8:31 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap, Julia Lawall

In order to improve NUMA-locality when serving getrandom(2) requests,
allocate one DRNG instance per node.

The DRNG instance that is present right from the start of the kernel is
reused as the first per-NUMA-node DRNG. For all remaining online NUMA
nodes a new DRNG instance is allocated.

During boot time, the multiple DRNG instances are seeded sequentially.
With this, the first DRNG instance (referenced as the initial DRNG
in the code) is completely seeded with 256 bits of entropy before the
next DRNG instance is completely seeded.

When random numbers are requested, the NUMA-node-local DRNG is checked
whether it has been already fully seeded. If this is not the case, the
initial DRNG is used to serve the request.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Makefile        |   2 +
 drivers/char/lrng/lrng_internal.h |   5 ++
 drivers/char/lrng/lrng_numa.c     | 101 ++++++++++++++++++++++++++++++
 3 files changed, 108 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_numa.c

diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index 1d2a0211973d..0a32f22c2c1a 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -7,3 +7,5 @@ obj-y				+= lrng_pool.o lrng_aux.o \
 				   lrng_sw_noise.o lrng_archrandom.o \
 				   lrng_drng.o lrng_chacha20.o \
 				   lrng_interfaces.o \
+
+obj-$(CONFIG_NUMA)		+= lrng_numa.o
diff --git a/drivers/char/lrng/lrng_internal.h b/drivers/char/lrng/lrng_internal.h
index c9a7bccd14a0..c2b0a467548e 100644
--- a/drivers/char/lrng/lrng_internal.h
+++ b/drivers/char/lrng/lrng_internal.h
@@ -246,8 +246,13 @@ int lrng_drng_get_sleep(u8 *outbuf, u32 outbuflen);
 void lrng_drng_force_reseed(void);
 void lrng_drng_seed_work(struct work_struct *dummy);
 
+#ifdef CONFIG_NUMA
+struct lrng_drng **lrng_drng_instances(void);
+void lrng_drngs_numa_alloc(void);
+#else	/* CONFIG_NUMA */
 static inline struct lrng_drng **lrng_drng_instances(void) { return NULL; }
 static inline void lrng_drngs_numa_alloc(void) { return; }
+#endif /* CONFIG_NUMA */
 
 /************************** Health Test linking code **************************/
 
diff --git a/drivers/char/lrng/lrng_numa.c b/drivers/char/lrng/lrng_numa.c
new file mode 100644
index 000000000000..947c5b3ed517
--- /dev/null
+++ b/drivers/char/lrng/lrng_numa.c
@@ -0,0 +1,101 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG NUMA support
+ *
+ * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/lrng.h>
+#include <linux/slab.h>
+
+#include "lrng_internal.h"
+
+static struct lrng_drng **lrng_drng __read_mostly = NULL;
+
+struct lrng_drng **lrng_drng_instances(void)
+{
+	return lrng_drng;
+}
+
+/* Allocate the data structures for the per-NUMA node DRNGs */
+static void _lrng_drngs_numa_alloc(struct work_struct *work)
+{
+	struct lrng_drng **drngs;
+	struct lrng_drng *lrng_drng_init = lrng_drng_init_instance();
+	u32 node;
+	bool init_drng_used = false;
+
+	mutex_lock(&lrng_crypto_cb_update);
+
+	/* per-NUMA-node DRNGs are already present */
+	if (lrng_drng)
+		goto unlock;
+
+	drngs = kcalloc(nr_node_ids, sizeof(void *), GFP_KERNEL|__GFP_NOFAIL);
+	for_each_online_node(node) {
+		struct lrng_drng *drng;
+
+		if (!init_drng_used) {
+			drngs[node] = lrng_drng_init;
+			init_drng_used = true;
+			continue;
+		}
+
+		drng = kmalloc_node(sizeof(struct lrng_drng),
+				     GFP_KERNEL|__GFP_NOFAIL, node);
+		memset(drng, 0, sizeof(lrng_drng));
+
+		drng->crypto_cb = lrng_drng_init->crypto_cb;
+		drng->drng = drng->crypto_cb->lrng_drng_alloc(
+					LRNG_DRNG_SECURITY_STRENGTH_BYTES);
+		if (IS_ERR(drng->drng)) {
+			kfree(drng);
+			goto err;
+		}
+
+		mutex_init(&drng->lock);
+		spin_lock_init(&drng->spin_lock);
+
+		/*
+		 * No reseeding of NUMA DRNGs from previous DRNGs as this
+		 * would complicate the code. Let it simply reseed.
+		 */
+		lrng_drng_reset(drng);
+		drngs[node] = drng;
+
+		lrng_pool_inc_numa_node();
+		pr_info("DRNG for NUMA node %d allocated\n", node);
+	}
+
+	/* Ensure that all NUMA nodes receive changed memory here. */
+	mb();
+
+	if (!cmpxchg(&lrng_drng, NULL, drngs))
+		goto unlock;
+
+err:
+	for_each_online_node(node) {
+		struct lrng_drng *drng = drngs[node];
+
+		if (drng == lrng_drng_init)
+			continue;
+
+		if (drng) {
+			drng->crypto_cb->lrng_drng_dealloc(drng->drng);
+			kfree(drng);
+		}
+	}
+	kfree(drngs);
+
+unlock:
+	mutex_unlock(&lrng_crypto_cb_update);
+}
+
+static DECLARE_WORK(lrng_drngs_numa_alloc_work, _lrng_drngs_numa_alloc);
+
+void lrng_drngs_numa_alloc(void)
+{
+	schedule_work(&lrng_drngs_numa_alloc_work);
+}
-- 
2.24.1





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v27 03/12] LRNG - sysctls and /proc interface
  2020-01-09  8:29     ` [PATCH v27 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
  2020-01-09  8:30       ` [PATCH v27 01/12] Linux Random Number Generator Stephan Müller
  2020-01-09  8:31       ` [PATCH v27 02/12] LRNG - allocate one DRNG instance per NUMA node Stephan Müller
@ 2020-01-09  8:31       ` Stephan Müller
  2020-01-09  8:32       ` [PATCH v27 04/12] LRNG - add switchable DRNG support Stephan Müller
                         ` (9 subsequent siblings)
  12 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2020-01-09  8:31 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap, Julia Lawall

The LRNG sysctl interface provides the same controls as the existing
/dev/random implementation. These sysctls behave identically and are
implemented identically. The goal is to allow a possible merge of the
existing /dev/random implementation with this implementation which
implies that this patch tries have a very close similarity. Yet, all
sysctls are documented at [1].

In addition, it provides the file lrng_type which provides details about
the LRNG:

- the name of the DRNG that produces the random numbers for /dev/random,
/dev/urandom, getrandom(2)

- the hash used to produce random numbers from the entropy pool

- the number of secondary DRNG instances

- indicator whether the LRNG operates SP800-90B compliant

- indicator whether a high-resolution timer is identified - only with a
high-resolution timer the interrupt noise source will deliver sufficient
entropy

- indicator whether the LRNG has been minimally seeded (i.e. is the
secondary DRNG seeded with at least 128 bits of of entropy)

- indicator whether the LRNG has been fully seeded (i.e. is the
secondary DRNG seeded with at least 256 bits of entropy)

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

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Makefile          |   1 +
 drivers/char/lrng/lrng_interfaces.c |   1 -
 drivers/char/lrng/lrng_internal.h   |   4 +
 drivers/char/lrng/lrng_proc.c       | 163 ++++++++++++++++++++++++++++
 4 files changed, 168 insertions(+), 1 deletion(-)
 create mode 100644 drivers/char/lrng/lrng_proc.c

diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index 0a32f22c2c1a..e69c176f0161 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -9,3 +9,4 @@ obj-y				+= lrng_pool.o lrng_aux.o \
 				   lrng_interfaces.o \
 
 obj-$(CONFIG_NUMA)		+= lrng_numa.o
+obj-$(CONFIG_SYSCTL)		+= lrng_proc.o
diff --git a/drivers/char/lrng/lrng_interfaces.c b/drivers/char/lrng/lrng_interfaces.c
index ff40ed37ddd6..8c4bf53d86ec 100644
--- a/drivers/char/lrng/lrng_interfaces.c
+++ b/drivers/char/lrng/lrng_interfaces.c
@@ -34,7 +34,6 @@ static DECLARE_WAIT_QUEUE_HEAD(lrng_write_wait);
 static DECLARE_WAIT_QUEUE_HEAD(lrng_init_wait);
 static struct fasync_struct *fasync;
 
-struct ctl_table random_table[];
 /********************************** Helper ***********************************/
 
 /* Is the DRNG seed level too low? */
diff --git a/drivers/char/lrng/lrng_internal.h b/drivers/char/lrng/lrng_internal.h
index c2b0a467548e..349152d3c1b0 100644
--- a/drivers/char/lrng/lrng_internal.h
+++ b/drivers/char/lrng/lrng_internal.h
@@ -116,7 +116,11 @@ void lrng_cc20_init_state(struct chacha20_state *state);
 
 /********************************** /proc *************************************/
 
+#ifdef CONFIG_SYSCTL
+void lrng_pool_inc_numa_node(void);
+#else
 static inline void lrng_pool_inc_numa_node(void) { }
+#endif
 
 /****************************** LRNG interfaces *******************************/
 
diff --git a/drivers/char/lrng/lrng_proc.c b/drivers/char/lrng/lrng_proc.c
new file mode 100644
index 000000000000..f4ee01f61925
--- /dev/null
+++ b/drivers/char/lrng/lrng_proc.c
@@ -0,0 +1,163 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG proc and sysctl interfaces
+ *
+ * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#include <linux/lrng.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/sysctl.h>
+#include <linux/uuid.h>
+
+#include "lrng_internal.h"
+
+/*
+ * This function is used to return both the bootid UUID, and random
+ * UUID.  The difference is in whether table->data is NULL; if it is,
+ * then a new UUID is generated and returned to the user.
+ *
+ * If the user accesses this via the proc interface, the UUID will be
+ * returned as an ASCII string in the standard UUID format; if via the
+ * sysctl system call, as 16 bytes of binary data.
+ */
+static int lrng_proc_do_uuid(struct ctl_table *table, int write,
+			     void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	struct ctl_table fake_table;
+	unsigned char buf[64], tmp_uuid[16], *uuid;
+
+	uuid = table->data;
+	if (!uuid) {
+		uuid = tmp_uuid;
+		generate_random_uuid(uuid);
+	} else {
+		static DEFINE_SPINLOCK(bootid_spinlock);
+
+		spin_lock(&bootid_spinlock);
+		if (!uuid[8])
+			generate_random_uuid(uuid);
+		spin_unlock(&bootid_spinlock);
+	}
+
+	sprintf(buf, "%pU", uuid);
+
+	fake_table.data = buf;
+	fake_table.maxlen = sizeof(buf);
+
+	return proc_dostring(&fake_table, write, buffer, lenp, ppos);
+}
+
+static int lrng_proc_do_entropy(struct ctl_table *table, int write,
+				void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	struct ctl_table fake_table;
+	int entropy_count;
+
+	entropy_count = lrng_avail_entropy();
+
+	fake_table.data = &entropy_count;
+	fake_table.maxlen = sizeof(entropy_count);
+
+	return proc_dointvec(&fake_table, write, buffer, lenp, ppos);
+}
+
+static int lrng_sysctl_poolsize = LRNG_POOL_SIZE_BITS;
+static int lrng_min_write_thresh;
+static int lrng_max_write_thresh = LRNG_POOL_SIZE_BITS;
+static char lrng_sysctl_bootid[16];
+static int lrng_drng_reseed_max_min;
+
+struct ctl_table random_table[] = {
+	{
+		.procname	= "poolsize",
+		.data		= &lrng_sysctl_poolsize,
+		.maxlen		= sizeof(int),
+		.mode		= 0444,
+		.proc_handler	= proc_dointvec,
+	},
+	{
+		.procname	= "entropy_avail",
+		.maxlen		= sizeof(int),
+		.mode		= 0444,
+		.proc_handler	= lrng_proc_do_entropy,
+	},
+	{
+		.procname	= "write_wakeup_threshold",
+		.data		= &lrng_write_wakeup_bits,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec_minmax,
+		.extra1		= &lrng_min_write_thresh,
+		.extra2		= &lrng_max_write_thresh,
+	},
+	{
+		.procname	= "boot_id",
+		.data		= &lrng_sysctl_bootid,
+		.maxlen		= 16,
+		.mode		= 0444,
+		.proc_handler	= lrng_proc_do_uuid,
+	},
+	{
+		.procname	= "uuid",
+		.maxlen		= 16,
+		.mode		= 0444,
+		.proc_handler	= lrng_proc_do_uuid,
+	},
+	{
+		.procname       = "urandom_min_reseed_secs",
+		.data           = &lrng_drng_reseed_max_time,
+		.maxlen         = sizeof(int),
+		.mode           = 0644,
+		.proc_handler   = proc_dointvec,
+		.extra1		= &lrng_drng_reseed_max_min,
+	},
+	{ }
+};
+
+/* Number of online DRNGs */
+static u32 numa_drngs = 1;
+
+void lrng_pool_inc_numa_node(void)
+{
+	numa_drngs++;
+}
+
+static int lrng_proc_type_show(struct seq_file *m, void *v)
+{
+	struct lrng_drng *lrng_drng_init = lrng_drng_init_instance();
+	unsigned long flags = 0;
+	unsigned char buf[300];
+
+	lrng_drng_lock(lrng_drng_init, &flags);
+	snprintf(buf, sizeof(buf),
+		 "DRNG name: %s\n"
+		 "Hash for reading entropy pool: %s\n"
+		 "DRNG security strength: %d bits\n"
+		 "number of DRNG instances: %u\n"
+		 "SP800-90B compliance: %s\n"
+		 "High-resolution timer: %s\n"
+		 "LRNG minimally seeded: %s\n"
+		 "LRNG fully seeded: %s\n",
+		 lrng_drng_init->crypto_cb->lrng_drng_name(),
+		 lrng_drng_init->crypto_cb->lrng_hash_name(),
+		 LRNG_DRNG_SECURITY_STRENGTH_BITS, numa_drngs,
+		 lrng_sp80090b_compliant() ? "true" : "false",
+		 lrng_pool_highres_timer() ? "true" : "false",
+		 lrng_state_min_seeded() ? "true" : "false",
+		 lrng_state_fully_seeded() ? "true" : "false");
+	lrng_drng_unlock(lrng_drng_init, &flags);
+
+	seq_write(m, buf, strlen(buf));
+
+	return 0;
+}
+
+static int __init lrng_proc_type_init(void)
+{
+	proc_create_single("lrng_type", 0444, NULL, &lrng_proc_type_show);
+	return 0;
+}
+
+module_init(lrng_proc_type_init);
-- 
2.24.1





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v27 04/12] LRNG - add switchable DRNG support
  2020-01-09  8:29     ` [PATCH v27 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                         ` (2 preceding siblings ...)
  2020-01-09  8:31       ` [PATCH v27 03/12] LRNG - sysctls and /proc interface Stephan Müller
@ 2020-01-09  8:32       ` Stephan Müller
  2020-01-11  7:09         ` kbuild test robot
  2020-01-09  8:32       ` [PATCH v27 05/12] crypto: DRBG - externalize DRBG functions for LRNG Stephan Müller
                         ` (8 subsequent siblings)
  12 siblings, 1 reply; 162+ messages in thread
From: Stephan Müller @ 2020-01-09  8:32 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap, Julia Lawall

The DRNG switch support allows replacing the DRNG mechanism of the
LRNG. The switching support rests on the interface definition of
include/linux/lrng.h. A new DRNG is implemented by filling in the
interface defined in this header file.

In addition to the DRNG, the extension also has to provide a hash
implementation that is used to hash the entropy pool for random number
extraction.

Note: It is permissible to implement a DRNG whose operations may sleep.
However, the hash function must not sleep.

The switchable DRNG support allows replacing the DRNG at runtime.
However, only one DRNG extension is allowed to be loaded at any given
time. Before replacing it with another DRNG implementation, the possibly
existing DRNG extension must be unloaded.

The switchable DRNG extension activates the new DRNG during load time.
It is expected, however, that such a DRNG switch would be done only once
by an administrator to load the intended DRNG implementation.

It is permissible to compile DRNG extensions either as kernel modules or
statically. The initialization of the DRNG extension should be performed
with a late_initcall to ensure the extension is available when user
space starts but after all other initialization completed.
The initialization is performed by registering the function call data
structure with the lrng_set_drng_cb function. In order to unload the
DRNG extension, lrng_set_drng_cb must be invoked with the NULL
parameter.

The DRNG extension should always provide a security strength that is at
least as strong as LRNG_DRNG_SECURITY_STRENGTH_BITS.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Kconfig       |   7 ++
 drivers/char/lrng/Makefile      |   1 +
 drivers/char/lrng/lrng_switch.c | 179 ++++++++++++++++++++++++++++++++
 3 files changed, 187 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_switch.c

diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
index 56f13efd3592..cb701bb0b8b6 100644
--- a/drivers/char/lrng/Kconfig
+++ b/drivers/char/lrng/Kconfig
@@ -64,4 +64,11 @@ config LRNG_POOL_SIZE
 	default 7 if LRNG_POOL_SIZE_65536
 	default 8 if LRNG_POOL_SIZE_131072
 
+menuconfig LRNG_DRNG_SWITCH
+	bool "Support DRNG runtime switching"
+	help
+	  The Linux RNG per default uses a ChaCha20 DRNG that is
+	  accessible via the external interfaces. With this configuration
+	  option other DRNGs can be selected and loaded at runtime.
+
 endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index e69c176f0161..31cfe87c999e 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -10,3 +10,4 @@ obj-y				+= lrng_pool.o lrng_aux.o \
 
 obj-$(CONFIG_NUMA)		+= lrng_numa.o
 obj-$(CONFIG_SYSCTL)		+= lrng_proc.o
+obj-$(CONFIG_LRNG_DRNG_SWITCH)	+= lrng_switch.o
diff --git a/drivers/char/lrng/lrng_switch.c b/drivers/char/lrng/lrng_switch.c
new file mode 100644
index 000000000000..2c7468d8de09
--- /dev/null
+++ b/drivers/char/lrng/lrng_switch.c
@@ -0,0 +1,179 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG DRNG switching support
+ *
+ * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/lrng.h>
+
+#include "lrng_internal.h"
+
+static int lrng_drng_switch(struct lrng_drng *drng_store,
+			    const struct lrng_crypto_cb *cb, int node)
+{
+	const struct lrng_crypto_cb *old_cb;
+	unsigned long flags = 0;
+	int ret;
+	u8 seed[LRNG_DRNG_SECURITY_STRENGTH_BYTES];
+	void *new_drng = cb->lrng_drng_alloc(LRNG_DRNG_SECURITY_STRENGTH_BYTES);
+	void *old_drng, *new_hash, *old_hash;
+	bool sl = false, reset_drng = !lrng_get_available();
+
+	if (IS_ERR(new_drng)) {
+		pr_warn("could not allocate new DRNG for NUMA node %d (%ld)\n",
+			node, PTR_ERR(new_drng));
+		return PTR_ERR(new_drng);
+	}
+
+	new_hash = cb->lrng_hash_alloc(seed, sizeof(seed));
+	if (IS_ERR(new_hash)) {
+		pr_warn("could not allocate new LRNG pool hash (%ld)\n",
+			PTR_ERR(new_hash));
+		cb->lrng_drng_dealloc(new_drng);
+		return PTR_ERR(new_hash);
+	}
+
+	lrng_drng_lock(drng_store, &flags);
+
+	/*
+	 * Pull from existing DRNG to seed new DRNG regardless of seed status
+	 * of old DRNG -- the entropy state for the DRNG is left unchanged which
+	 * implies that als the new DRNG is reseeded when deemed necessary. This
+	 * seeding of the new DRNG shall only ensure that the new DRNG has the
+	 * same entropy as the old DRNG.
+	 */
+	ret = drng_store->crypto_cb->lrng_drng_generate_helper(
+				drng_store->drng, seed, sizeof(seed));
+	lrng_drng_unlock(drng_store, &flags);
+
+	if (ret < 0) {
+		reset_drng = true;
+		pr_warn("getting random data from DRNG failed for NUMA node %d "
+			"(%d)\n", node, ret);
+	} else {
+		/* seed new DRNG with data */
+		ret = cb->lrng_drng_seed_helper(new_drng, seed, ret);
+		if (ret < 0) {
+			reset_drng = true;
+			pr_warn("seeding of new DRNG failed for NUMA node %d "
+				"(%d)\n", node, ret);
+		} else {
+			pr_debug("seeded new DRNG of NUMA node %d instance "
+				 "from old DRNG instance\n", node);
+		}
+	}
+
+	mutex_lock(&drng_store->lock);
+	/*
+	 * If we switch the DRNG from the initial ChaCha20 DRNG to something
+	 * else, there is a lock transition from spin lock to mutex (see
+	 * lrng_drng_is_atomic and how the lock is taken in lrng_drng_lock).
+	 * Thus, we need to take both locks during the transition phase.
+	 */
+	if (lrng_drng_is_atomic(drng_store)) {
+		spin_lock_irqsave(&drng_store->spin_lock, flags);
+		sl = true;
+	}
+
+	if (reset_drng)
+		lrng_drng_reset(drng_store);
+
+	old_drng = drng_store->drng;
+	old_cb = drng_store->crypto_cb;
+	drng_store->drng = new_drng;
+	drng_store->crypto_cb = cb;
+
+	old_hash = drng_store->hash;
+	drng_store->hash = new_hash;
+	pr_info("Entropy pool read-hash allocated for DRNG for NUMA node %d\n",
+		node);
+
+	if (sl)
+		spin_unlock_irqrestore(&drng_store->spin_lock, flags);
+	mutex_unlock(&drng_store->lock);
+
+	/* ChaCha20 serves as atomic instance left untouched. */
+	if (old_drng != &chacha20) {
+		old_cb->lrng_drng_dealloc(old_drng);
+		old_cb->lrng_hash_dealloc(old_hash);
+	}
+
+	pr_info("DRNG of NUMA node %d switched\n", node);
+
+	return 0;
+}
+
+/**
+ * Switch the existing DRNG instances with new using the new crypto callbacks.
+ * The caller must hold the lrng_crypto_cb_update lock.
+ */
+static int lrng_drngs_switch(const struct lrng_crypto_cb *cb)
+{
+	struct lrng_drng **lrng_drng = lrng_drng_instances();
+	struct lrng_drng *lrng_drng_init = lrng_drng_init_instance();
+	int ret = 0;
+
+	/* Update DRNG */
+	if (lrng_drng) {
+		u32 node;
+
+		for_each_online_node(node) {
+			if (lrng_drng[node])
+				ret = lrng_drng_switch(lrng_drng[node], cb,
+						       node);
+		}
+	} else {
+		ret = lrng_drng_switch(lrng_drng_init, cb, 0);
+	}
+
+	if (!ret)
+		lrng_set_available();
+
+	return 0;
+}
+
+/**
+ * lrng_set_drng_cb - Register new cryptographic callback functions for DRNG
+ * The registering implies that all old DRNG states are replaced with new
+ * DRNG states.
+ * @cb: Callback functions to be registered -- if NULL, use the default
+ *	callbacks pointing to the ChaCha20 DRNG.
+ * @return: 0 on success, < 0 on error
+ */
+int lrng_set_drng_cb(const struct lrng_crypto_cb *cb)
+{
+	struct lrng_drng *lrng_drng_init = lrng_drng_init_instance();
+	int ret;
+
+	if (!cb)
+		cb = &lrng_cc20_crypto_cb;
+
+	mutex_lock(&lrng_crypto_cb_update);
+
+	/*
+	 * If a callback other than the default is set, allow it only to be
+	 * set back to the default callback. This ensures that multiple
+	 * different callbacks can be registered at the same time. If a
+	 * callback different from the current callback and the default
+	 * callback shall be set, the current callback must be deregistered
+	 * (e.g. the kernel module providing it must be unloaded) and the new
+	 * implementation can be registered.
+	 */
+	if ((cb != &lrng_cc20_crypto_cb) &&
+	    (lrng_drng_init->crypto_cb != &lrng_cc20_crypto_cb)) {
+		pr_warn("disallow setting new cipher callbacks, unload the old "
+			"callbacks first!\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	ret = lrng_drngs_switch(cb);
+
+out:
+	mutex_unlock(&lrng_crypto_cb_update);
+	return ret;
+}
+EXPORT_SYMBOL(lrng_set_drng_cb);
-- 
2.24.1





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v27 05/12] crypto: DRBG - externalize DRBG functions for LRNG
  2020-01-09  8:29     ` [PATCH v27 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                         ` (3 preceding siblings ...)
  2020-01-09  8:32       ` [PATCH v27 04/12] LRNG - add switchable DRNG support Stephan Müller
@ 2020-01-09  8:32       ` Stephan Müller
  2020-01-09  8:32       ` [PATCH v27 06/12] LRNG - add SP800-90A DRBG extension Stephan Müller
                         ` (7 subsequent siblings)
  12 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2020-01-09  8:32 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap, Julia Lawall

This patch allows several DRBG functions to be called by the LRNG kernel
code paths outside the drbg.c file.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 crypto/drbg.c         | 16 ++++++++++------
 include/crypto/drbg.h |  7 +++++++
 2 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/crypto/drbg.c b/crypto/drbg.c
index b6929eb5f565..5561dd0f09e1 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -113,7 +113,7 @@
  * the SHA256 / AES 256 over other ciphers. Thus, the favored
  * DRBGs are the latest entries in this array.
  */
-static const struct drbg_core drbg_cores[] = {
+const struct drbg_core drbg_cores[] = {
 #ifdef CONFIG_CRYPTO_DRBG_CTR
 	{
 		.flags = DRBG_CTR | DRBG_STRENGTH128,
@@ -190,6 +190,7 @@ static const struct drbg_core drbg_cores[] = {
 	},
 #endif /* CONFIG_CRYPTO_DRBG_HMAC */
 };
+EXPORT_SYMBOL(drbg_cores);
 
 static int drbg_uninstantiate(struct drbg_state *drbg);
 
@@ -205,7 +206,7 @@ static int drbg_uninstantiate(struct drbg_state *drbg);
  * Return: normalized strength in *bytes* value or 32 as default
  *	   to counter programming errors
  */
-static inline unsigned short drbg_sec_strength(drbg_flag_t flags)
+unsigned short drbg_sec_strength(drbg_flag_t flags)
 {
 	switch (flags & DRBG_STRENGTH_MASK) {
 	case DRBG_STRENGTH128:
@@ -218,6 +219,7 @@ static inline unsigned short drbg_sec_strength(drbg_flag_t flags)
 		return 32;
 	}
 }
+EXPORT_SYMBOL(drbg_sec_strength);
 
 /*
  * FIPS 140-2 continuous self test for the noise source
@@ -1202,7 +1204,7 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
 }
 
 /* Free all substructures in a DRBG state without the DRBG state structure */
-static inline void drbg_dealloc_state(struct drbg_state *drbg)
+void drbg_dealloc_state(struct drbg_state *drbg)
 {
 	if (!drbg)
 		return;
@@ -1223,12 +1225,13 @@ static inline void drbg_dealloc_state(struct drbg_state *drbg)
 		drbg->fips_primed = false;
 	}
 }
+EXPORT_SYMBOL(drbg_dealloc_state);
 
 /*
  * Allocate all sub-structures for a DRBG state.
  * The DRBG state structure must already be allocated.
  */
-static inline int drbg_alloc_state(struct drbg_state *drbg)
+int drbg_alloc_state(struct drbg_state *drbg)
 {
 	int ret = -ENOMEM;
 	unsigned int sb_size = 0;
@@ -1307,6 +1310,7 @@ static inline int drbg_alloc_state(struct drbg_state *drbg)
 	drbg_dealloc_state(drbg);
 	return ret;
 }
+EXPORT_SYMBOL(drbg_alloc_state);
 
 /*************************************************************************
  * DRBG interface functions
@@ -1874,8 +1878,7 @@ static int drbg_kcapi_sym_ctr(struct drbg_state *drbg,
  *
  * return: flags
  */
-static inline void drbg_convert_tfm_core(const char *cra_driver_name,
-					 int *coreref, bool *pr)
+void drbg_convert_tfm_core(const char *cra_driver_name, int *coreref, bool *pr)
 {
 	int i = 0;
 	size_t start = 0;
@@ -1902,6 +1905,7 @@ static inline void drbg_convert_tfm_core(const char *cra_driver_name,
 		}
 	}
 }
+EXPORT_SYMBOL(drbg_convert_tfm_core);
 
 static int drbg_kcapi_init(struct crypto_tfm *tfm)
 {
diff --git a/include/crypto/drbg.h b/include/crypto/drbg.h
index 8c9af21efce1..c63b20375235 100644
--- a/include/crypto/drbg.h
+++ b/include/crypto/drbg.h
@@ -282,4 +282,11 @@ enum drbg_prefixes {
 	DRBG_PREFIX3
 };
 
+extern int drbg_alloc_state(struct drbg_state *drbg);
+extern void drbg_dealloc_state(struct drbg_state *drbg);
+extern void drbg_convert_tfm_core(const char *cra_driver_name, int *coreref,
+				  bool *pr);
+extern const struct drbg_core drbg_cores[];
+extern unsigned short drbg_sec_strength(drbg_flag_t flags);
+
 #endif /* _DRBG_H */
-- 
2.24.1





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v27 06/12] LRNG - add SP800-90A DRBG extension
  2020-01-09  8:29     ` [PATCH v27 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                         ` (4 preceding siblings ...)
  2020-01-09  8:32       ` [PATCH v27 05/12] crypto: DRBG - externalize DRBG functions for LRNG Stephan Müller
@ 2020-01-09  8:32       ` Stephan Müller
  2020-01-09  8:33       ` [PATCH v27 07/12] LRNG - add kernel crypto API PRNG extension Stephan Müller
                         ` (6 subsequent siblings)
  12 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2020-01-09  8:32 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap, Julia Lawall

Using the LRNG switchable DRNG support, the SP800-90A DRBG extension is
implemented.

The DRBG uses the kernel crypto API DRBG implementation. In addition, it
uses the kernel crypto API SHASH support to provide the hashing
operation.

The DRBG supports the choice of either a CTR DRBG using AES-256, HMAC
DRBG with SHA-512 core or Hash DRBG with SHA-512 core. The used core can
be selected with the module parameter lrng_drbg_type. The default is the
CTR DRBG.

When compiling the DRBG extension statically, the DRBG is loaded at
late_initcall stage which implies that with the start of user space, the
user space interfaces of getrandom(2), /dev/random and /dev/urandom
provide random data produced by an SP800-90A DRBG.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Kconfig     |  11 ++
 drivers/char/lrng/Makefile    |   1 +
 drivers/char/lrng/lrng_drbg.c | 261 ++++++++++++++++++++++++++++++++++
 3 files changed, 273 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_drbg.c

diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
index cb701bb0b8b6..15fb623d9d1f 100644
--- a/drivers/char/lrng/Kconfig
+++ b/drivers/char/lrng/Kconfig
@@ -71,4 +71,15 @@ menuconfig LRNG_DRNG_SWITCH
 	  accessible via the external interfaces. With this configuration
 	  option other DRNGs can be selected and loaded at runtime.
 
+if LRNG_DRNG_SWITCH
+config LRNG_DRBG
+	tristate "SP800-90A support for the LRNG"
+	select CRYPTO_DRBG_MENU
+	select CRYPTO_CMAC if CRYPTO_DRBG_CTR
+	help
+	  Enable the SP800-90A DRBG support for the LRNG. Once the
+	  module is loaded, output from /dev/random, /dev/urandom,
+	  getrandom(2), or get_random_bytes is provided by a DRBG.
+endif # LRNG_DRNG_SWITCH
+
 endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index 31cfe87c999e..0d320fcb7b9e 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -11,3 +11,4 @@ obj-y				+= lrng_pool.o lrng_aux.o \
 obj-$(CONFIG_NUMA)		+= lrng_numa.o
 obj-$(CONFIG_SYSCTL)		+= lrng_proc.o
 obj-$(CONFIG_LRNG_DRNG_SWITCH)	+= lrng_switch.o
+obj-$(CONFIG_LRNG_DRBG)		+= lrng_drbg.o
diff --git a/drivers/char/lrng/lrng_drbg.c b/drivers/char/lrng/lrng_drbg.c
new file mode 100644
index 000000000000..605e573e5aa6
--- /dev/null
+++ b/drivers/char/lrng/lrng_drbg.c
@@ -0,0 +1,261 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * Backend for the LRNG providing the cryptographic primitives using the
+ * kernel crypto API and its DRBG.
+ *
+ * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <crypto/drbg.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/lrng.h>
+
+/*
+ * Define a DRBG plus a hash / MAC used to extract data from the entropy pool.
+ * For LRNG_HASH_NAME you can use a hash or a MAC (HMAC or CMAC) of your choice
+ * (Note, you should use the suggested selections below -- using SHA-1 or MD5
+ * is not wise). The idea is that the used cipher primitive can be selected to
+ * be the same as used for the DRBG. I.e. the LRNG only uses one cipher
+ * primitive using the same cipher implementation with the options offered in
+ * the following. This means, if the CTR DRBG is selected and AES-NI is present,
+ * both the CTR DRBG and the selected cmac(aes) use AES-NI.
+ *
+ * The security strengths of the DRBGs are all 256 bits according to
+ * SP800-57 section 5.6.1.
+ *
+ * This definition is allowed to be changed.
+ */
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+static unsigned int lrng_drbg_type = 0;
+#elif defined CONFIG_CRYPTO_DRBG_HMAC
+static unsigned int lrng_drbg_type = 1;
+#elif defined CONFIG_CRYPTO_DRBG_HASH
+static unsigned int lrng_drbg_type = 2;
+#else
+#error "Unknown DRBG in use"
+#endif
+
+/* The parameter must be r/o in sysfs as otherwise races appear. */
+module_param(lrng_drbg_type, uint, 0444);
+MODULE_PARM_DESC(lrng_drbg_type, "DRBG type used for LRNG (0->CTR_DRBG, "
+				 "1->HMAC_DRBG, 2->Hash_DRBG)");
+
+struct lrng_drbg {
+	const char *hash_name;
+	const char *drbg_core;
+};
+
+static const struct lrng_drbg lrng_drbg_types[] = {
+	{	/* CTR_DRBG with AES-256 using derivation function */
+		.hash_name = "cmac(aes)",
+		.drbg_core = "drbg_nopr_ctr_aes256",
+	}, {	/* HMAC_DRBG with SHA-512 */
+		.hash_name = "sha512",
+		.drbg_core = "drbg_nopr_hmac_sha512",
+	}, {	/* Hash_DRBG with SHA-512 using derivation function */
+		.hash_name = "sha512",
+		.drbg_core = "drbg_nopr_sha512"
+	}
+};
+
+struct lrng_hash_info {
+	struct shash_desc shash;
+	char ctx[];
+};
+
+static int lrng_drbg_drng_seed_helper(void *drng, const u8 *inbuf, u32 inbuflen)
+{
+	struct drbg_state *drbg = (struct drbg_state *)drng;
+	LIST_HEAD(seedlist);
+	struct drbg_string data;
+	int ret;
+
+	drbg_string_fill(&data, inbuf, inbuflen);
+	list_add_tail(&data.list, &seedlist);
+	ret = drbg->d_ops->update(drbg, &seedlist, drbg->seeded);
+
+	if (ret >= 0)
+		drbg->seeded = true;
+
+	return ret;
+}
+
+static int lrng_drbg_drng_generate_helper(void *drng, u8 *outbuf, u32 outbuflen)
+{
+	struct drbg_state *drbg = (struct drbg_state *)drng;
+
+	return drbg->d_ops->generate(drbg, outbuf, outbuflen, NULL);
+}
+
+static void *lrng_drbg_drng_alloc(u32 sec_strength)
+{
+	struct drbg_state *drbg;
+	int coreref = -1;
+	bool pr = false;
+	int ret;
+
+	drbg_convert_tfm_core(lrng_drbg_types[lrng_drbg_type].drbg_core,
+			      &coreref, &pr);
+	if (coreref < 0)
+		return ERR_PTR(-EFAULT);
+
+	drbg = kzalloc(sizeof(struct drbg_state), GFP_KERNEL);
+	if (!drbg)
+		return ERR_PTR(-ENOMEM);
+
+	drbg->core = &drbg_cores[coreref];
+	drbg->seeded = false;
+	ret = drbg_alloc_state(drbg);
+	if (ret)
+		goto err;
+
+	if (sec_strength > drbg_sec_strength(drbg->core->flags)) {
+		pr_err("Security strength of DRBG (%u bits) lower than "
+		       "requested by LRNG (%u bits)\n",
+			drbg_sec_strength(drbg->core->flags) * 8,
+			sec_strength * 8);
+		goto dealloc;
+	}
+
+	if (sec_strength < drbg_sec_strength(drbg->core->flags))
+		pr_warn("Security strength of DRBG (%u bits) higher than "
+			"requested by LRNG (%u bits)\n",
+			drbg_sec_strength(drbg->core->flags) * 8,
+			sec_strength * 8);
+
+	pr_info("DRBG with %s core allocated\n", drbg->core->backend_cra_name);
+
+	return drbg;
+
+dealloc:
+	if (drbg->d_ops)
+		drbg->d_ops->crypto_fini(drbg);
+	drbg_dealloc_state(drbg);
+err:
+	kfree(drbg);
+	return ERR_PTR(-EINVAL);
+}
+
+static void lrng_drbg_drng_dealloc(void *drng)
+{
+	struct drbg_state *drbg = (struct drbg_state *)drng;
+
+	drbg_dealloc_state(drbg);
+	kzfree(drbg);
+	pr_info("DRBG deallocated\n");
+}
+
+static void *lrng_drbg_hash_alloc(const u8 *key, u32 keylen)
+{
+	struct lrng_hash_info *lrng_hash;
+	struct crypto_shash *tfm;
+	int size, ret;
+
+	tfm = crypto_alloc_shash(lrng_drbg_types[lrng_drbg_type].hash_name,
+				 0, 0);
+	if (IS_ERR(tfm)) {
+		pr_err("could not allocate hash %s\n",
+		       lrng_drbg_types[lrng_drbg_type].hash_name);
+		return ERR_CAST(tfm);
+	}
+
+	size = sizeof(struct lrng_hash_info) + crypto_shash_descsize(tfm);
+	lrng_hash = kmalloc(size, GFP_KERNEL);
+	if (!lrng_hash) {
+		crypto_free_shash(tfm);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	lrng_hash->shash.tfm = tfm;
+
+	/* If the used hash is no MAC, ignore the ENOSYS return code */
+	ret = crypto_shash_setkey(tfm, key, keylen);
+	if (ret && ret != -ENOSYS) {
+		pr_err("could not set the key for MAC\n");
+		crypto_free_shash(tfm);
+		kfree(lrng_hash);
+		return ERR_PTR(ret);
+	}
+
+	pr_info("Hash %s allocated\n",
+		lrng_drbg_types[lrng_drbg_type].hash_name);
+
+	return lrng_hash;
+}
+
+static void lrng_drbg_hash_dealloc(void *hash)
+{
+	struct lrng_hash_info *lrng_hash = (struct lrng_hash_info *)hash;
+	struct shash_desc *shash = &lrng_hash->shash;
+	struct crypto_shash *tfm = shash->tfm;
+
+	crypto_free_shash(tfm);
+	kfree(lrng_hash);
+	pr_info("Hash deallocated\n");
+}
+
+static u32 lrng_drbg_hash_digestsize(void *hash)
+{
+	struct lrng_hash_info *lrng_hash = (struct lrng_hash_info *)hash;
+	struct shash_desc *shash = &lrng_hash->shash;
+
+	return crypto_shash_digestsize(shash->tfm);
+}
+
+static int lrng_drbg_hash_buffer(void *hash, const u8 *inbuf, u32 inbuflen,
+				 u8 *digest)
+{
+	struct lrng_hash_info *lrng_hash = (struct lrng_hash_info *)hash;
+	struct shash_desc *shash = &lrng_hash->shash;
+
+	return crypto_shash_digest(shash, inbuf, inbuflen, digest);
+}
+
+static const char *lrng_drbg_name(void)
+{
+	return lrng_drbg_types[lrng_drbg_type].drbg_core;
+}
+
+static const char *lrng_hash_name(void)
+{
+	return lrng_drbg_types[lrng_drbg_type].hash_name;
+}
+
+const static struct lrng_crypto_cb lrng_drbg_crypto_cb = {
+	.lrng_drng_name			= lrng_drbg_name,
+	.lrng_hash_name			= lrng_hash_name,
+	.lrng_drng_alloc		= lrng_drbg_drng_alloc,
+	.lrng_drng_dealloc		= lrng_drbg_drng_dealloc,
+	.lrng_drng_seed_helper		= lrng_drbg_drng_seed_helper,
+	.lrng_drng_generate_helper	= lrng_drbg_drng_generate_helper,
+	.lrng_drng_generate_helper_full	= lrng_drbg_drng_generate_helper,
+	.lrng_hash_alloc		= lrng_drbg_hash_alloc,
+	.lrng_hash_dealloc		= lrng_drbg_hash_dealloc,
+	.lrng_hash_digestsize		= lrng_drbg_hash_digestsize,
+	.lrng_hash_buffer		= lrng_drbg_hash_buffer,
+};
+
+static int __init lrng_drbg_init(void)
+{
+	if (lrng_drbg_type >= ARRAY_SIZE(lrng_drbg_types)) {
+		pr_err("lrng_drbg_type parameter too large (given %u - max: %lu)",
+		       lrng_drbg_type,
+		       (unsigned long)ARRAY_SIZE(lrng_drbg_types) - 1);
+		return -EAGAIN;
+	}
+	return lrng_set_drng_cb(&lrng_drbg_crypto_cb);
+}
+
+static void __exit lrng_drbg_exit(void)
+{
+	lrng_set_drng_cb(NULL);
+}
+
+late_initcall(lrng_drbg_init);
+module_exit(lrng_drbg_exit);
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
+MODULE_DESCRIPTION("Linux Random Number Generator - SP800-90A DRBG backend");
-- 
2.24.1





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v27 07/12] LRNG - add kernel crypto API PRNG extension
  2020-01-09  8:29     ` [PATCH v27 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                         ` (5 preceding siblings ...)
  2020-01-09  8:32       ` [PATCH v27 06/12] LRNG - add SP800-90A DRBG extension Stephan Müller
@ 2020-01-09  8:33       ` Stephan Müller
  2020-01-09  8:33       ` [PATCH v27 08/12] crypto: provide access to a static Jitter RNG state Stephan Müller
                         ` (5 subsequent siblings)
  12 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2020-01-09  8:33 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap, Julia Lawall

Add runtime-pluggable support for all PRNGs that are accessible via
the kernel crypto API, including hardware PRNGs. The PRNG is selected
with the module parameter drng_name where the name must be one that the
kernel crypto API can resolve into an RNG.

This allows using of the kernel crypto API PRNG implementations that
provide an interface to hardware PRNGs. Using this extension,
the LRNG uses the hardware PRNGs to generate random numbers. An
example is the S390 CPACF support providing such a PRNG.

The hash is provided by a kernel crypto API SHASH whose digest size
complies with the seedsize of the PRNG.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Kconfig      |  10 +
 drivers/char/lrng/Makefile     |   1 +
 drivers/char/lrng/lrng_kcapi.c | 328 +++++++++++++++++++++++++++++++++
 3 files changed, 339 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_kcapi.c

diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
index 15fb623d9d1f..0d070a3897dd 100644
--- a/drivers/char/lrng/Kconfig
+++ b/drivers/char/lrng/Kconfig
@@ -80,6 +80,16 @@ config LRNG_DRBG
 	  Enable the SP800-90A DRBG support for the LRNG. Once the
 	  module is loaded, output from /dev/random, /dev/urandom,
 	  getrandom(2), or get_random_bytes is provided by a DRBG.
+
+config LRNG_KCAPI
+	tristate "Kernel Crypto API support for the LRNG"
+	select CRYPTO_RNG
+	help
+	  Enable the support for generic pseudo-random number
+	  generators offered by the kernel crypto API with the
+	  LRNG. Once the module is loaded, output from /dev/random,
+	  /dev/urandom, getrandom(2), or get_random_bytes is
+	  provided by the selected kernel crypto API RNG.
 endif # LRNG_DRNG_SWITCH
 
 endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index 0d320fcb7b9e..94b2dfb2dfdb 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -12,3 +12,4 @@ obj-$(CONFIG_NUMA)		+= lrng_numa.o
 obj-$(CONFIG_SYSCTL)		+= lrng_proc.o
 obj-$(CONFIG_LRNG_DRNG_SWITCH)	+= lrng_switch.o
 obj-$(CONFIG_LRNG_DRBG)		+= lrng_drbg.o
+obj-$(CONFIG_LRNG_KCAPI)	+= lrng_kcapi.o
diff --git a/drivers/char/lrng/lrng_kcapi.c b/drivers/char/lrng/lrng_kcapi.c
new file mode 100644
index 000000000000..206c56e513a0
--- /dev/null
+++ b/drivers/char/lrng/lrng_kcapi.c
@@ -0,0 +1,328 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * Backend for the LRNG providing the cryptographic primitives using the
+ * kernel crypto API.
+ *
+ * Copyright (C) 2018 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <crypto/hash.h>
+#include <crypto/rng.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/lrng.h>
+
+static char *drng_name = NULL;
+module_param(drng_name, charp, 0444);
+MODULE_PARM_DESC(drng_name, "Kernel crypto API name of DRNG");
+
+static char *pool_hash = "sha512";
+module_param(pool_hash, charp, 0444);
+MODULE_PARM_DESC(pool_hash,
+		 "Kernel crypto API name of hash or keyed message digest to read the entropy pool");
+
+static char *seed_hash = NULL;
+module_param(seed_hash, charp, 0444);
+MODULE_PARM_DESC(seed_hash,
+		 "Kernel crypto API name of hash with output size equal to seedsize of DRNG to bring seed string to the size required by the DRNG");
+
+struct lrng_hash_info {
+	struct shash_desc shash;
+	char ctx[];
+};
+
+struct lrng_drng_info {
+	struct crypto_rng *kcapi_rng;
+	struct lrng_hash_info *lrng_hash;
+};
+
+static struct lrng_hash_info *_lrng_kcapi_hash_alloc(const char *name)
+{
+	struct lrng_hash_info *lrng_hash;
+	struct crypto_shash *tfm;
+	int size;
+
+	if (!name) {
+		pr_err("Hash name missing\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	tfm = crypto_alloc_shash(name, 0, 0);
+	if (IS_ERR(tfm)) {
+		pr_err("could not allocate hash %s\n", name);
+		return ERR_CAST(tfm);
+	}
+
+	size = sizeof(struct lrng_hash_info) + crypto_shash_descsize(tfm);
+	lrng_hash = kmalloc(size, GFP_KERNEL);
+	if (!lrng_hash) {
+		crypto_free_shash(tfm);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	lrng_hash->shash.tfm = tfm;
+
+	return lrng_hash;
+}
+
+static inline u32 _lrng_kcapi_hash_digestsize(struct lrng_hash_info *lrng_hash)
+{
+	struct shash_desc *shash = &lrng_hash->shash;
+	struct crypto_shash *tfm = shash->tfm;
+
+	return crypto_shash_digestsize(tfm);
+}
+
+static inline void _lrng_kcapi_hash_free(struct lrng_hash_info *lrng_hash)
+{
+	struct shash_desc *shash = &lrng_hash->shash;
+	struct crypto_shash *tfm = shash->tfm;
+
+	crypto_free_shash(tfm);
+	kfree(lrng_hash);
+}
+
+static void *lrng_kcapi_hash_alloc(const u8 *key, u32 keylen)
+{
+	struct lrng_hash_info *lrng_hash;
+	int ret;
+
+	lrng_hash = _lrng_kcapi_hash_alloc(pool_hash);
+	if (IS_ERR(lrng_hash))
+		return ERR_CAST(lrng_hash);
+
+	/* If the used hash is no MAC, ignore the ENOSYS return code */
+	ret = crypto_shash_setkey(lrng_hash->shash.tfm, key, keylen);
+	if (ret && ret != -ENOSYS) {
+		pr_err("could not set the key for MAC\n");
+		_lrng_kcapi_hash_free(lrng_hash);
+		return ERR_PTR(ret);
+	}
+
+	pr_info("Hash %s allocated\n", pool_hash);
+
+	return lrng_hash;
+}
+
+static void lrng_kcapi_hash_dealloc(void *hash)
+{
+	struct lrng_hash_info *lrng_hash = (struct lrng_hash_info *)hash;
+
+	_lrng_kcapi_hash_free(lrng_hash);
+	pr_info("Hash %s deallocated\n", pool_hash);
+}
+
+static u32 lrng_kcapi_hash_digestsize(void *hash)
+{
+	struct lrng_hash_info *lrng_hash = (struct lrng_hash_info *)hash;
+
+	return _lrng_kcapi_hash_digestsize(lrng_hash);
+}
+
+static int lrng_kcapi_hash_buffer(void *hash, const u8 *inbuf, u32 inbuflen,
+				  u8 *digest)
+{
+	struct lrng_hash_info *lrng_hash = (struct lrng_hash_info *)hash;
+	struct shash_desc *shash = &lrng_hash->shash;
+
+	return crypto_shash_digest(shash, inbuf, inbuflen, digest);
+}
+
+static int lrng_kcapi_drng_seed_helper(void *drng, const u8 *inbuf,
+				       u32 inbuflen)
+{
+	struct lrng_drng_info *lrng_drng_info = (struct lrng_drng_info *)drng;
+	struct crypto_rng *kcapi_rng = lrng_drng_info->kcapi_rng;
+	struct lrng_hash_info *lrng_hash = lrng_drng_info->lrng_hash;
+
+	if (lrng_hash) {
+		struct shash_desc *shash = &lrng_hash->shash;
+		u32 digestsize = _lrng_kcapi_hash_digestsize(lrng_hash);
+		u8 digest[64] __aligned(8);
+		int ret;
+
+		BUG_ON(digestsize > sizeof(digest));
+
+		ret = crypto_shash_digest(shash, inbuf, inbuflen, digest);
+		if (ret)
+			return ret;
+
+		ret = crypto_rng_reset(kcapi_rng, digest, digestsize);
+		if (ret)
+			return ret;
+
+		memzero_explicit(digest, digestsize);
+
+		return 0;
+	} else {
+		return crypto_rng_reset(kcapi_rng, inbuf, inbuflen);
+	}
+}
+
+static int lrng_kcapi_drng_generate_helper(void *drng, u8 *outbuf,
+					   u32 outbuflen)
+{
+	struct lrng_drng_info *lrng_drng_info = (struct lrng_drng_info *)drng;
+	struct crypto_rng *kcapi_rng = lrng_drng_info->kcapi_rng;
+	int ret = crypto_rng_get_bytes(kcapi_rng, outbuf, outbuflen);
+
+	if (ret < 0)
+		return ret;
+
+	return outbuflen;
+}
+
+static void *lrng_kcapi_drng_alloc(u32 sec_strength)
+{
+	struct lrng_drng_info *lrng_drng_info;
+	struct crypto_rng *kcapi_rng;
+	int seedsize;
+	void *ret =  ERR_PTR(-ENOMEM);
+
+	if (!drng_name) {
+		pr_err("DRNG name missing\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (!memcmp(drng_name, "drbg", 4)) {
+		pr_err("SP800-90A DRBG cannot be allocated using lrng_kcapi "
+		       "backend, use lrng_drbg backend instead\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (!memcmp(drng_name, "stdrng", 6)) {
+		pr_err("stdrng cannot be allocated using lrng_kcapi backend, "
+		       "it is too unspecific and potentially may allocate the "
+		       "DRBG\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	lrng_drng_info = kmalloc(sizeof(*lrng_drng_info), GFP_KERNEL);
+	if (!lrng_drng_info)
+		return ERR_PTR(-ENOMEM);
+
+	kcapi_rng = crypto_alloc_rng(drng_name, 0, 0);
+	if (IS_ERR(kcapi_rng)) {
+		pr_err("DRNG %s cannot be allocated\n", drng_name);
+		ret = ERR_CAST(kcapi_rng);
+		goto free;
+	}
+	lrng_drng_info->kcapi_rng = kcapi_rng;
+
+	seedsize =  crypto_rng_seedsize(kcapi_rng);
+
+	if (sec_strength > seedsize)
+		pr_info("Seedsize DRNG (%u bits) lower than "
+			"security strength of LRNG noise source (%u bits)\n",
+			crypto_rng_seedsize(kcapi_rng) * 8,
+			sec_strength * 8);
+
+	if (seedsize) {
+		struct lrng_hash_info *lrng_hash;
+
+		if (!seed_hash) {
+			switch (seedsize) {
+			case 32:
+				seed_hash = "sha256";
+				break;
+			case 48:
+				seed_hash = "sha384";
+				break;
+			case 64:
+				seed_hash = "sha512";
+				break;
+			default:
+				pr_err("Seed size %d cannot be processed\n",
+				       seedsize);
+				goto dealloc;
+				break;
+			}
+		}
+
+		lrng_hash = _lrng_kcapi_hash_alloc(seed_hash);
+		if (IS_ERR(lrng_hash)) {
+			ret = ERR_CAST(lrng_hash);
+			goto dealloc;
+		}
+
+		if (seedsize != _lrng_kcapi_hash_digestsize(lrng_hash)) {
+			pr_err("Seed hash output size not equal to DRNG seed "
+			       "size\n");
+			_lrng_kcapi_hash_free(lrng_hash);
+			ret = ERR_PTR(-EINVAL);
+			goto dealloc;
+		}
+
+		lrng_drng_info->lrng_hash = lrng_hash;
+
+		pr_info("Seed hash %s allocated\n", seed_hash);
+	} else {
+		lrng_drng_info->lrng_hash = NULL;
+	}
+
+	pr_info("Kernel crypto API DRNG %s allocated\n", drng_name);
+
+	return lrng_drng_info;
+
+dealloc:
+	crypto_free_rng(kcapi_rng);
+free:
+	kfree(lrng_drng_info);
+	return ret;
+}
+
+static void lrng_kcapi_drng_dealloc(void *drng)
+{
+	struct lrng_drng_info *lrng_drng_info = (struct lrng_drng_info *)drng;
+	struct crypto_rng *kcapi_rng = lrng_drng_info->kcapi_rng;
+	struct lrng_hash_info *lrng_hash = lrng_drng_info->lrng_hash;
+
+	crypto_free_rng(kcapi_rng);
+	if (lrng_hash) {
+		_lrng_kcapi_hash_free(lrng_hash);
+		pr_info("Seed hash %s deallocated\n", seed_hash);
+	}
+	kfree(lrng_drng_info);
+	pr_info("DRNG %s deallocated\n", drng_name);
+}
+
+static const char *lrng_kcapi_drng_name(void)
+{
+	return drng_name;
+}
+
+static const char *lrng_kcapi_pool_hash(void)
+{
+	return pool_hash;
+}
+
+const static struct lrng_crypto_cb lrng_kcapi_crypto_cb = {
+	.lrng_drng_name			= lrng_kcapi_drng_name,
+	.lrng_hash_name			= lrng_kcapi_pool_hash,
+	.lrng_drng_alloc		= lrng_kcapi_drng_alloc,
+	.lrng_drng_dealloc		= lrng_kcapi_drng_dealloc,
+	.lrng_drng_seed_helper		= lrng_kcapi_drng_seed_helper,
+	.lrng_drng_generate_helper	= lrng_kcapi_drng_generate_helper,
+	.lrng_drng_generate_helper_full	= lrng_kcapi_drng_generate_helper,
+	.lrng_hash_alloc		= lrng_kcapi_hash_alloc,
+	.lrng_hash_dealloc		= lrng_kcapi_hash_dealloc,
+	.lrng_hash_digestsize		= lrng_kcapi_hash_digestsize,
+	.lrng_hash_buffer		= lrng_kcapi_hash_buffer,
+};
+
+static int __init lrng_kcapi_init(void)
+{
+	return lrng_set_drng_cb(&lrng_kcapi_crypto_cb);
+}
+static void __exit lrng_kcapi_exit(void)
+{
+	lrng_set_drng_cb(NULL);
+}
+
+late_initcall(lrng_kcapi_init);
+module_exit(lrng_kcapi_exit);
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
+MODULE_DESCRIPTION("Linux Random Number Generator - kernel crypto API DRNG backend");
-- 
2.24.1





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v27 08/12] crypto: provide access to a static Jitter RNG state
  2020-01-09  8:29     ` [PATCH v27 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                         ` (6 preceding siblings ...)
  2020-01-09  8:33       ` [PATCH v27 07/12] LRNG - add kernel crypto API PRNG extension Stephan Müller
@ 2020-01-09  8:33       ` Stephan Müller
  2020-01-09  8:34       ` [PATCH v27 09/12] LRNG - add Jitter RNG fast noise source Stephan Müller
                         ` (4 subsequent siblings)
  12 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2020-01-09  8:33 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap, Julia Lawall

To support the LRNG operation which uses the Jitter RNG separately
from the kernel crypto API, at a time where potentially the regular
memory management is not yet initialized, the Jitter RNG needs to
provide a state whose memory is defined at compile time. As only once
instance will ever be needed by the LRNG, define once static memory
block which is solely to be used by the LRNG.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 crypto/jitterentropy-kcapi.c                  |  3 +--
 crypto/jitterentropy.c                        | 25 ++++++++++++++++++-
 .../crypto/internal}/jitterentropy.h          |  3 +++
 3 files changed, 28 insertions(+), 3 deletions(-)
 rename {crypto => include/crypto/internal}/jitterentropy.h (84%)

diff --git a/crypto/jitterentropy-kcapi.c b/crypto/jitterentropy-kcapi.c
index a5ce8f96790f..11b00e9f37f3 100644
--- a/crypto/jitterentropy-kcapi.c
+++ b/crypto/jitterentropy-kcapi.c
@@ -43,8 +43,7 @@
 #include <linux/time.h>
 #include <linux/crypto.h>
 #include <crypto/internal/rng.h>
-
-#include "jitterentropy.h"
+#include <crypto/internal/jitterentropy.h>
 
 /***************************************************************************
  * Helper function
diff --git a/crypto/jitterentropy.c b/crypto/jitterentropy.c
index 042157f0d28b..529c9db13e64 100644
--- a/crypto/jitterentropy.c
+++ b/crypto/jitterentropy.c
@@ -103,7 +103,7 @@ struct rand_data {
  * Helper functions
  ***************************************************************************/
 
-#include "jitterentropy.h"
+#include <crypto/internal/jitterentropy.h>
 
 /**
  * Update of the loop count used for the next round of
@@ -639,3 +639,26 @@ int jent_entropy_init(void)
 
 	return 0;
 }
+
+struct rand_data *jent_lrng_entropy_collector(void)
+{
+	static unsigned char lrng_jent_mem[JENT_MEMORY_SIZE];
+	static struct rand_data lrng_jent_state = {
+		.data		= 0,
+		.old_data	= 0,
+		.prev_time	= 0,
+		.last_delta	= 0,
+		.last_delta2	= 0,
+		.osr		= 1,
+		.mem		= lrng_jent_mem,
+		.memlocation	= 0,
+		.memblocks	= JENT_MEMORY_BLOCKSIZE,
+		.memblocksize	= JENT_MEMORY_BLOCKS,
+		.memaccessloops	= JENT_MEMORY_ACCESSLOOPS,
+	};
+
+	if (jent_entropy_init())
+		return NULL;
+
+	return &lrng_jent_state;
+}
diff --git a/crypto/jitterentropy.h b/include/crypto/internal/jitterentropy.h
similarity index 84%
rename from crypto/jitterentropy.h
rename to include/crypto/internal/jitterentropy.h
index c83fff32d130..6e07d86eac82 100644
--- a/crypto/jitterentropy.h
+++ b/include/crypto/internal/jitterentropy.h
@@ -15,3 +15,6 @@ extern int jent_read_entropy(struct rand_data *ec, unsigned char *data,
 extern struct rand_data *jent_entropy_collector_alloc(unsigned int osr,
 						      unsigned int flags);
 extern void jent_entropy_collector_free(struct rand_data *entropy_collector);
+
+/* Access to statically allocated Jitter RNG instance */
+extern struct rand_data *jent_lrng_entropy_collector(void);
-- 
2.24.1





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v27 09/12] LRNG - add Jitter RNG fast noise source
  2020-01-09  8:29     ` [PATCH v27 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                         ` (7 preceding siblings ...)
  2020-01-09  8:33       ` [PATCH v27 08/12] crypto: provide access to a static Jitter RNG state Stephan Müller
@ 2020-01-09  8:34       ` Stephan Müller
  2020-01-10  0:24         ` Randy Dunlap
  2020-01-09  8:34       ` [PATCH v27 10/12] LRNG - add SP800-90B compliant health tests Stephan Müller
                         ` (3 subsequent siblings)
  12 siblings, 1 reply; 162+ messages in thread
From: Stephan Müller @ 2020-01-09  8:34 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap, Julia Lawall

The Jitter RNG fast noise source implemented as part of the kernel
crypto API is queried for 256 bits of entropy at the time the seed
buffer managed by the LRNG is about to be filled.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Kconfig     | 11 +++++
 drivers/char/lrng/Makefile    |  1 +
 drivers/char/lrng/lrng_jent.c | 87 +++++++++++++++++++++++++++++++++++
 3 files changed, 99 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_jent.c

diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
index 0d070a3897dd..10b7cbdb8c8e 100644
--- a/drivers/char/lrng/Kconfig
+++ b/drivers/char/lrng/Kconfig
@@ -92,4 +92,15 @@ config LRNG_KCAPI
 	  provided by the selected kernel crypto API RNG.
 endif # LRNG_DRNG_SWITCH
 
+config LRNG_JENT
+	bool "Enable Jitter RNG as LRNG Seed Source"
+	select CRYPTO_JITTERENTROPY
+	help
+	  The Linux RNG may use the Jitter RNG as noise source. Enabling
+	  this option enables the use of the Jitter RNG. Its default
+	  entropy level is 16 bits of entropy per 256 data bits delivered
+	  by the Jitter RNG. This entropy level can be changed at boot
+	  time or at runtime with the lrng_base.jitterrng configuration
+	  variable.
+
 endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index 94b2dfb2dfdb..4f5b6f38f0c4 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -13,3 +13,4 @@ obj-$(CONFIG_SYSCTL)		+= lrng_proc.o
 obj-$(CONFIG_LRNG_DRNG_SWITCH)	+= lrng_switch.o
 obj-$(CONFIG_LRNG_DRBG)		+= lrng_drbg.o
 obj-$(CONFIG_LRNG_KCAPI)	+= lrng_kcapi.o
+obj-$(CONFIG_LRNG_JENT)		+= lrng_jent.o
diff --git a/drivers/char/lrng/lrng_jent.c b/drivers/char/lrng/lrng_jent.c
new file mode 100644
index 000000000000..97c0d192e9c8
--- /dev/null
+++ b/drivers/char/lrng/lrng_jent.c
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG Fast Noise Source: Jitter RNG
+ *
+ * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/types.h>
+#include <crypto/internal/jitterentropy.h>
+
+#include "lrng_internal.h"
+
+/*
+ * Estimated entropy of data is a 16th of LRNG_DRNG_SECURITY_STRENGTH_BITS.
+ * Albeit a full entropy assessment is provided for the noise source indicating
+ * that it provides high entropy rates and considering that it deactivates
+ * when it detects insufficient hardware, the chosen under estimation of
+ * entropy is considered to be acceptable to all reviewers.
+ */
+static u32 jitterrng = LRNG_DRNG_SECURITY_STRENGTH_BITS>>4;
+module_param(jitterrng, uint, 0644);
+MODULE_PARM_DESC(jitterrng, "Entropy in bits of 256 data bits from Jitter "
+			    "RNG noise source");
+
+/**
+ * Get Jitter RNG entropy
+ *
+ * @outbuf buffer to store entropy
+ * @outbuflen length of buffer
+ * @return > 0 on success where value provides the added entropy in bits
+ *	   0 if no fast source was available
+ */
+static struct rand_data *lrng_jent_state;
+
+u32 lrng_get_jent(u8 *outbuf, unsigned int outbuflen)
+{
+	int ret;
+	u32 ent_bits = jitterrng;
+	unsigned long flags;
+	static DEFINE_SPINLOCK(lrng_jent_lock);
+	static int lrng_jent_initialized = 0;
+
+	spin_lock_irqsave(&lrng_jent_lock, flags);
+
+	if (!ent_bits || (lrng_jent_initialized == -1)) {
+		spin_unlock_irqrestore(&lrng_jent_lock, flags);
+		return 0;
+	}
+
+	if (!lrng_jent_initialized) {
+		lrng_jent_state = jent_lrng_entropy_collector();
+		if (!lrng_jent_state) {
+			jitterrng = 0;
+			lrng_jent_initialized = -1;
+			spin_unlock_irqrestore(&lrng_jent_lock, flags);
+			pr_info("Jitter RNG unusable on current system\n");
+			return 0;
+		}
+		lrng_jent_initialized = 1;
+		pr_debug("Jitter RNG working on current system\n");
+	}
+	ret = jent_read_entropy(lrng_jent_state, outbuf, outbuflen);
+	spin_unlock_irqrestore(&lrng_jent_lock, flags);
+
+	if (ret) {
+		pr_debug("Jitter RNG failed with %d\n", ret);
+		return 0;
+	}
+
+	/* Obtain entropy statement */
+	if (outbuflen != LRNG_DRNG_SECURITY_STRENGTH_BYTES)
+		ent_bits = (ent_bits * outbuflen<<3) /
+			   LRNG_DRNG_SECURITY_STRENGTH_BITS;
+	/* Cap entropy to buffer size in bits */
+	ent_bits = min_t(u32, ent_bits, outbuflen<<3);
+	pr_debug("obtained %u bits of entropy from Jitter RNG noise source\n",
+		 ent_bits);
+
+	return ent_bits;
+}
+
+u32 lrng_jent_entropylevel(void)
+{
+	return min_t(u32, jitterrng, LRNG_DRNG_SECURITY_STRENGTH_BITS);
+}
-- 
2.24.1





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v27 10/12] LRNG - add SP800-90B compliant health tests
  2020-01-09  8:29     ` [PATCH v27 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                         ` (8 preceding siblings ...)
  2020-01-09  8:34       ` [PATCH v27 09/12] LRNG - add Jitter RNG fast noise source Stephan Müller
@ 2020-01-09  8:34       ` Stephan Müller
  2020-01-10  0:20         ` Randy Dunlap
  2020-01-09  8:35       ` [PATCH v27 11/12] LRNG - add interface for gathering of raw entropy Stephan Müller
                         ` (2 subsequent siblings)
  12 siblings, 1 reply; 162+ messages in thread
From: Stephan Müller @ 2020-01-09  8:34 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap, Julia Lawall

Implement health tests for LRNG's slow noise sources as mandated by
SP-800-90B The file contains the following health tests:

- stuck test: The stuck test calculates the first, second and third
  discrete derivative of the time stamp to be processed by the LFSR.
  Only if all three values are non-zero, the received time delta is
  considered to be non-stuck.

- SP800-90B Repetition Count Test (RCT): The LRNG uses an enhanced
  version of the RCT specified in SP800-90B section 4.4.1. Instead of
  counting identical back-to-back values, the input to the RCT is the
  counting of the stuck values during the processing of received
  interrupt events. The RCT is applied with alpha=2^-30 compliant to
  the recommendation of FIPS 140-2 IG 9.8. During the counting operation,
  the LRNG always calculates the RCT cut-off value of C. If that value
  exceeds the allowed cut-off value, the LRNG will trigger the health
  test failure discussed below. An error is logged to the kernel log
  that such RCT failure occurred. This test is only applied and
  enforced in FIPS mode, i.e. when the kernel compiled with
  CONFIG_CONFIG_FIPS is started with fips=1.

- SP800-90B Adaptive Proportion Test (APT): The LRNG implements the
  APT as defined in SP800-90B section 4.4.2. The applied significance
  level again is alpha=2^-30 compliant to the recommendation of FIPS
  140-2 IG 9.8.

The aforementioned health tests are applied to the first 1,024 time stamps
obtained from interrupt events. In case one error is identified for either
the RCT, or the APT, the collected entropy is invalidated and the
SP800-90B startup health test is restarted.

As long as the SP800-90B startup health test is not completed, all LRNG
random number output interfaces that may block will block and not generate
any data. This implies that only those potentially blocking interfaces are
defined to provide random numbers that are seeded with the interrupt noise
source being SP800-90B compliant. All other output interfaces will not be
affected by the SP800-90B startup test and thus are not considered
SP800-90B compliant.

At runtime, the SP800-90B APT and RCT are applied to each time stamp
generated for a received interrupt. When either the APT and RCT indicates
a noise source failure, the LRNG is reset to a state it has immediately
after boot:

- all entropy counters are set to zero

- the SP800-90B startup tests are re-performed which implies that
getrandom(2) would block again until new entropy was collected

To summarize, the following rules apply:

• SP800-90B compliant output interfaces

  - /dev/random

  - getrandom(2) system call

  -  get_random_bytes kernel-internal interface when being triggered by
     the callback registered with add_random_ready_callback

• SP800-90B non-compliant output interfaces

  - /dev/urandom

  - get_random_bytes kernel-internal interface called directly

  - randomize_page kernel-internal interface

  - get_random_u32 and get_random_u64 kernel-internal interfaces

  - get_random_u32_wait, get_random_u64_wait, get_random_int_wait, and
    get_random_long_wait kernel-internal interfaces

If either the RCT, or the APT health test fails irrespective whether
during initialization or runtime, the following actions occur:

  1. The entropy of the entire entropy pool is invalidated.

  2. All DRNGs are reset which imply that they are treated as being
     not seeded and require a reseed during next invocation.

  3. The SP800-90B startup health test are initiated with all
     implications of the startup tests. That implies that from that point
     on, new events must be observed and its entropy must be inserted into
     the entropy pool before random numbers are calculated from the
     entropy pool.

Further details on the SP800-90B compliance and the availability of all
test tools required to perform all tests mandated by SP800-90B are
provided at [1].

The entire health testing code is compile-time configurable.

The patch provides a CONFIG_BROKEN configuration of the APT / RCT cutoff
values which have a high likelihood to trigger the health test failure.
The BROKEN APT cutoff is set to the exact mean of the expected value if
the time stamps are equally distributed (512 time stamps divided by 16
possible values due to using the 4 LSB of the time stamp). The BROKEN
RCT cutoff value is set to 1 which is likely to be triggered during
regular operation.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Kconfig       |  56 +++++
 drivers/char/lrng/Makefile      |   1 +
 drivers/char/lrng/lrng_health.c | 409 ++++++++++++++++++++++++++++++++
 3 files changed, 466 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_health.c

diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
index 10b7cbdb8c8e..7b2bb3da066c 100644
--- a/drivers/char/lrng/Kconfig
+++ b/drivers/char/lrng/Kconfig
@@ -103,4 +103,60 @@ config LRNG_JENT
 	  time or at runtime with the lrng_base.jitterrng configuration
 	  variable.
 
+config LRNG_HEALTH_TESTS
+	bool "Enable noise source online health tests"
+	help
+	  The online health tests validate the noise source at
+	  runtime for fatal errors. These tests include SP800-90B
+	  compliant tests which are invoked if the system is booted
+	  with fips=1. In case of fatal errors during active
+	  SP800-90B tests, the issue is logged and the noise
+	  data is discarded. These tests are required for full
+	  compliance with SP800-90B.
+
+	  If unsure, say Y.
+
+config LRNG_RCT_BROKEN
+	bool "SP800-90B RCT with dangerous low cutoff value"
+	depends on LRNG_HEALTH_TESTS
+	depends on BROKEN
+	default n
+	help
+	  This option enables a dangerously low SP800-90B repetitive
+	  count test (RCT) cutoff value which makes it very likely
+	  that the RCT is triggered to raise a self test failure.
+
+	  This option is ONLY intended for developers wanting to
+	  test the effectiveness of the SP800-90B RCT health test.
+
+	  If unsure, say N.
+
+config LRNG_APT_BROKEN
+	bool "SP800-90B APT with dangerous low cutoff value"
+	depends on LRNG_HEALTH_TESTS
+	depends on BROKEN
+	default n
+	help
+	  This option enables a dangerously low SP800-90B adaptive
+	  proportion test (APT) cutoff value which makes it very
+	  likely that the RCT is triggered to raise a self test
+	  failure.
+
+	  This option is ONLY intended for developers wanting to
+	  test the effectiveness of the SP800-90B APT health test.
+
+	  If unsure, say N.
+
+# Default taken from SP800-90B sec 4.4.1 - significance level 2^-30
+config LRNG_RCT_CUTOFF
+	int
+	default 30 if !LRNG_RCT_BROKEN
+	default 1 if LRNG_RCT_BROKEN
+
+# Default taken from SP800-90B sec 4.4.2 - significance level 2^-30
+config LRNG_APT_CUTOFF
+	int
+	default 325 if !LRNG_APT_BROKEN
+	default 32 if LRNG_APT_BROKEN
+
 endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index 4f5b6f38f0c4..c3008763dd14 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -14,3 +14,4 @@ obj-$(CONFIG_LRNG_DRNG_SWITCH)	+= lrng_switch.o
 obj-$(CONFIG_LRNG_DRBG)		+= lrng_drbg.o
 obj-$(CONFIG_LRNG_KCAPI)	+= lrng_kcapi.o
 obj-$(CONFIG_LRNG_JENT)		+= lrng_jent.o
+obj-$(CONFIG_LRNG_HEALTH_TESTS)	+= lrng_health.o
diff --git a/drivers/char/lrng/lrng_health.c b/drivers/char/lrng/lrng_health.c
new file mode 100644
index 000000000000..da8b42b96918
--- /dev/null
+++ b/drivers/char/lrng/lrng_health.c
@@ -0,0 +1,409 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * Linux Random Number Generator (LRNG) Health Testing
+ *
+ * Copyright (C) 2019 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/fips.h>
+#include <linux/module.h>
+
+#include "lrng_internal.h"
+
+/* Stuck Test */
+struct lrng_stuck_test {
+	u32 last_time;		/* Stuck test: time of previous IRQ */
+	u32 last_delta;		/* Stuck test: delta of previous IRQ */
+	u32 last_delta2;	/* Stuck test: 2. time derivation of prev IRQ */
+};
+
+/* Repetition Count Test */
+struct lrng_rct {
+	atomic_t rct_count;	/* Number of stuck values */
+};
+
+/* Adaptive Proportion Test */
+struct lrng_apt {
+	/* Data window size */
+#define LRNG_APT_WINDOW_SIZE	512
+	/* LSB of time stamp to process */
+#define LRNG_APT_LSB		16
+#define LRNG_APT_WORD_MASK	(LRNG_APT_LSB - 1)
+	atomic_t apt_count;		/* APT counter */
+	atomic_t apt_base;		/* APT base reference */
+
+	atomic_t apt_trigger;
+	bool apt_base_set;	/* Is APT base set? */
+};
+
+/* The health test code must operate lock-less */
+struct lrng_health {
+	struct lrng_rct rct;
+	struct lrng_apt apt;
+
+	bool health_test_enabled;
+
+	/* SP800-90B startup health tests */
+#define LRNG_SP80090B_STARTUP_SAMPLES  1024
+#define LRNG_SP80090B_STARTUP_BLOCKS   ((LRNG_SP80090B_STARTUP_SAMPLES + \
+					 LRNG_APT_WINDOW_SIZE - 1) /    \
+					LRNG_APT_WINDOW_SIZE)
+	bool sp80090b_startup_done;
+	atomic_t sp80090b_startup_blocks;
+};
+
+static struct lrng_health lrng_health = {
+	.rct.rct_count = ATOMIC_INIT(0),
+
+	.apt.apt_count = ATOMIC_INIT(0),
+	.apt.apt_base = ATOMIC_INIT(-1),
+	.apt.apt_trigger = ATOMIC_INIT(LRNG_APT_WINDOW_SIZE),
+	.apt.apt_base_set = false,
+
+	.health_test_enabled = true,
+
+	.sp80090b_startup_blocks = ATOMIC_INIT(LRNG_SP80090B_STARTUP_BLOCKS),
+	.sp80090b_startup_done = false,
+};
+
+static DEFINE_PER_CPU(struct lrng_stuck_test, lrng_stuck_test);
+
+static inline bool lrng_sp80090b_health_requested(void)
+{
+	/* Health tests are only requested in FIPS mode */
+	return fips_enabled;
+}
+
+static inline bool lrng_sp80090b_health_enabled(void)
+{
+	struct lrng_health *health = &lrng_health;
+
+	return lrng_sp80090b_health_requested() && health->health_test_enabled;
+}
+
+/***************************************************************************
+ * SP800-90B Compliance
+ *
+ * If the Linux-RNG is booted into FIPS mode, the following interfaces
+ * provide an SP800-90B compliant noise source:
+ *
+ * * /dev/random
+ * * getrandom(2)
+ * * get_random_bytes when using it in conjunction with
+ *   add_random_ready_callback
+ *
+ * All other interfaces, including /dev/urandom or get_random_bytes without
+ * the add_random_ready_callback cannot claim to use an SP800-90B compliant
+ * noise source.
+ ***************************************************************************/
+
+/**
+ * Perform SP800-90B startup testing
+ */
+static inline void lrng_sp80090b_startup(struct lrng_health *health)
+{
+	if (!health->sp80090b_startup_done &&
+	    atomic_dec_and_test(&health->sp80090b_startup_blocks)) {
+		health->sp80090b_startup_done = true;
+		pr_info("SP800-90B startup health tests completed\n");
+		lrng_init_ops(0);
+
+		/*
+		 * Force a reseed of DRNGs to ensure they are seeded with
+		 * entropy that passed the SP800-90B health tests.
+		 * As the DRNG always will reseed before generating
+		 * random numbers, it does not need a reseed trigger.
+		 */
+		lrng_drng_force_reseed();
+	}
+}
+
+/**
+ * Handle failure of SP800-90B startup testing
+ */
+static inline void lrng_sp80090b_startup_failure(struct lrng_health *health)
+{
+	/* Reset of LRNG and its entropy - NOTE: we are in atomic context */
+	lrng_reset();
+
+	/*
+	 * Reset the SP800-90B startup test.
+	 *
+	 * NOTE SP800-90B section 4.3 bullet 4 does not specify what
+	 * exactly is to be done in case of failure! Thus, we do what
+	 * makes sense, i.e. restarting the health test and thus gating
+	 * the output function of /dev/random and getrandom(2).
+	 */
+	atomic_set(&health->sp80090b_startup_blocks,
+		   LRNG_SP80090B_STARTUP_BLOCKS);
+}
+
+/**
+ * Handle failure of SP800-90B runtime testing
+ */
+static inline void lrng_sp80090b_runtime_failure(struct lrng_health *health)
+{
+	lrng_sp80090b_startup_failure(health);
+	health->sp80090b_startup_done = false;
+}
+
+static inline void lrng_sp80090b_failure(struct lrng_health *health)
+{
+	if (health->sp80090b_startup_done) {
+		pr_err("SP800-90B runtime health test failure - invalidating "
+		       "all existing entropy and initiate SP800-90B startup\n");
+		lrng_sp80090b_runtime_failure(health);
+	} else {
+		pr_err("SP800-90B startup test failure - resetting\n");
+		lrng_sp80090b_startup_failure(health);
+	}
+}
+
+/**
+ * Is the SP800-90B startup testing complete?
+ *
+ * This function is called by the LRNG to determine whether to unblock
+ * a certain user interface. Therefore, only the potentially blocking
+ * user interfaces are considered SP800-90B compliant.
+ */
+bool lrng_sp80090b_startup_complete(void)
+{
+	struct lrng_health *health = &lrng_health;
+
+	return (lrng_sp80090b_health_enabled()) ? health->sp80090b_startup_done:
+						  true;
+}
+
+bool lrng_sp80090b_compliant(void)
+{
+	struct lrng_health *health = &lrng_health;
+
+	return lrng_sp80090b_health_enabled() && health->sp80090b_startup_done;
+}
+
+/***************************************************************************
+ * Adaptive Proportion Test
+ *
+ * This test complies with SP800-90B section 4.4.2.
+ ***************************************************************************/
+
+/**
+ * Reset the APT counter
+ *
+ * @health [in] Reference to health state
+ */
+static inline void lrng_apt_reset(struct lrng_health *health,
+				  unsigned int time_masked)
+{
+	struct lrng_apt *apt = &health->apt;
+
+	pr_debug("APT value %d for base %d\n",
+		 atomic_read(&apt->apt_count), atomic_read(&apt->apt_base));
+
+	/* Reset APT */
+	atomic_set(&apt->apt_count, 0);
+	atomic_set(&apt->apt_base, time_masked);
+}
+
+static inline void lrng_apt_restart(struct lrng_health *health)
+{
+	struct lrng_apt *apt = &health->apt;
+
+	atomic_set(&apt->apt_trigger, LRNG_APT_WINDOW_SIZE);
+}
+
+/**
+ * Insert a new entropy event into APT
+ *
+ * This function does is void as it does not decide about the fate of a time
+ * stamp. An APT failure can only happen at the same time of a stuck test
+ * failure. Thus, the stuck failure will already decide how the time stamp
+ * is handled.
+ *
+ * @health [in] Reference to health state
+ * @now_time [in] Time stamp to process
+ */
+static inline void lrng_apt_insert(struct lrng_health *health,
+				   unsigned int now_time)
+{
+	struct lrng_apt *apt = &health->apt;
+
+	if (!lrng_sp80090b_health_requested())
+		return;
+
+	now_time &= LRNG_APT_WORD_MASK;
+
+	/* Initialization of APT */
+	if (!apt->apt_base_set) {
+		atomic_set(&apt->apt_base, now_time);
+		apt->apt_base_set = true;
+		return;
+	}
+
+	if (now_time == (unsigned int)atomic_read(&apt->apt_base)) {
+		u32 apt_val = (u32)atomic_inc_return_relaxed(&apt->apt_count);
+
+		if (apt_val >= CONFIG_LRNG_APT_CUTOFF)
+			lrng_sp80090b_failure(health);
+	}
+
+	if (atomic_dec_and_test(&apt->apt_trigger)) {
+		lrng_apt_restart(health);
+		lrng_apt_reset(health, now_time);
+		lrng_sp80090b_startup(health);
+	}
+}
+
+/***************************************************************************
+ * Repetition Count Test
+ *
+ * The LRNG uses an enhanced version of the Repetition Count Test
+ * (RCT) specified in SP800-90B section 4.4.1. Instead of counting identical
+ * back-to-back values, the input to the RCT is the counting of the stuck
+ * values while filling the entropy pool.
+ *
+ * The RCT is applied with an alpha of 2^-30 compliant to FIPS 140-2 IG 9.8.
+ *
+ * During the counting operation, the LRNG always calculates the RCT
+ * cut-off value of C. If that value exceeds the allowed cut-off value,
+ * the LRNG will invalidate all entropy for the entropy pool which implies
+ * that no data can be extracted from the entropy pool unless new entropy
+ * is received.
+ ***************************************************************************/
+
+/**
+ * Hot code path - Insert data for Repetition Count Test
+ *
+ * @health: Reference to health information
+ * @stuck: Decision of stuck test
+ */
+static inline void lrng_rct(struct lrng_health *health, int stuck)
+{
+	struct lrng_rct *rct = &health->rct;
+
+	if (!lrng_sp80090b_health_requested())
+		return;
+
+	if (stuck) {
+		u32 rct_count = atomic_add_return_relaxed(1, &rct->rct_count);
+
+		pr_debug("RCT count: %u\n", rct_count);
+
+		/*
+		 * The cutoff value is based on the following consideration:
+		 * alpha = 2^-30 as recommended in FIPS 140-2 IG 9.8.
+		 * In addition, we imply an entropy value H of 1 bit as this
+		 * is the minimum entropy required to provide full entropy.
+		 *
+		 * Note, rct_count (which equals to value B in the
+		 * pseudo code of SP800-90B section 4.4.1) starts with zero.
+		 * Hence we need to subtract one from the cutoff value as
+		 * calculated following SP800-90B.
+		 */
+		if (rct_count >= CONFIG_LRNG_RCT_CUTOFF) {
+			atomic_set(&rct->rct_count, 0);
+
+			/*
+			 * APT must start anew as we consider all previously
+			 * recorded data to contain no entropy.
+			 */
+			lrng_apt_restart(health);
+
+			lrng_sp80090b_failure(health);
+		}
+	} else {
+		atomic_set(&rct->rct_count, 0);
+	}
+}
+
+/***************************************************************************
+ * Stuck Test
+ *
+ * Checking the:
+ *      1st derivative of the event occurrence (time delta)
+ *      2nd derivative of the event occurrence (delta of time deltas)
+ *      3rd derivative of the event occurrence (delta of delta of time deltas)
+ *
+ * All values must always be non-zero. The stuck test is only valid disabled if
+ * high-resolution time stamps are identified after initialization.
+ ***************************************************************************/
+
+static inline u32 lrng_delta(u32 prev, u32 next)
+{
+	/*
+	 * Note that this (unsigned) subtraction does yield the correct value
+	 * in the wraparound-case, i.e. when next < prev.
+	 */
+	return (next - prev);
+}
+
+/**
+ * Hot code path
+ *
+ * @health: Reference to health information
+ * @now: Event time
+ * @return: 0 event occurrence not stuck (good time stamp)
+ *	    != 0 event occurrence stuck (reject time stamp)
+ */
+static inline int lrng_irq_stuck(struct lrng_stuck_test *stuck, u32 now_time)
+{
+	u32 delta = lrng_delta(stuck->last_time, now_time);
+	u32 delta2 = lrng_delta(stuck->last_delta, delta);
+	u32 delta3 = lrng_delta(stuck->last_delta2, delta2);
+
+	stuck->last_time = now_time;
+	stuck->last_delta = delta;
+	stuck->last_delta2 = delta2;
+
+	if (!delta || !delta2 || !delta3)
+		return 1;
+
+	return 0;
+}
+
+/***************************************************************************
+ * Health test interfaces
+ ***************************************************************************/
+
+/**
+ * Disable all health tests
+ */
+void lrng_health_disable(void)
+{
+	struct lrng_health *health = &lrng_health;
+
+	health->health_test_enabled = false;
+
+	if (lrng_sp80090b_health_requested())
+		pr_warn("SP800-90B compliance requested but the Linux RNG is "
+			"NOT SP800-90B compliant\n");
+}
+
+/**
+ * Hot code path - Perform health test on time stamp received from an event
+ *
+ * @now_time Time stap
+ */
+enum lrng_health_res lrng_health_test(u32 now_time)
+{
+	struct lrng_health *health = &lrng_health;
+	struct lrng_stuck_test *stuck_test = this_cpu_ptr(&lrng_stuck_test);
+	int stuck;
+
+	if (!health->health_test_enabled)
+		return lrng_health_pass;
+
+	lrng_apt_insert(health, now_time);
+
+	stuck = lrng_irq_stuck(stuck_test, now_time);
+	lrng_rct(health, stuck);
+	if (stuck) {
+		/* SP800-90B disallows using a failing health test time stamp */
+		return lrng_sp80090b_health_requested() ?
+			lrng_health_fail_drop : lrng_health_fail_use;
+	}
+
+	return lrng_health_pass;
+}
-- 
2.24.1





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v27 11/12] LRNG - add interface for gathering of raw entropy
  2020-01-09  8:29     ` [PATCH v27 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                         ` (9 preceding siblings ...)
  2020-01-09  8:34       ` [PATCH v27 10/12] LRNG - add SP800-90B compliant health tests Stephan Müller
@ 2020-01-09  8:35       ` Stephan Müller
  2020-01-09  8:35       ` [PATCH v27 12/12] LRNG - add power-on and runtime self-tests Stephan Müller
  2020-01-15 10:31       ` [PATCH v28 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
  12 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2020-01-09  8:35 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap, Julia Lawall

The test interface allows a privileged process to capture the raw
unconditioned noise that is collected by the LRNG for statistical
analysis. Such testing allows the analysis how much entropy
the interrupt noise source provides on a given platform.
Extracted noise data is not used to seed the LRNG. This
is a test interface and not appropriate for production systems.
Yet, the interface is considered to be sufficiently secured for
production systems.

Access to the data is given through the lrng_raw debugfs file. The
data buffer should be multiples of sizeof(u32) to fill the entire
buffer. Using the option lrng_testing.boot_test=1 the raw noise of
the first 1000 entropy events since boot can be sampled.

This test interface allows generating the data required for
analysis whether the LRNG is in compliance with SP800-90B
sections 3.1.3 and 3.1.4.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Kconfig        |  16 ++
 drivers/char/lrng/Makefile       |   1 +
 drivers/char/lrng/lrng_testing.c | 271 +++++++++++++++++++++++++++++++
 3 files changed, 288 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_testing.c

diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
index 7b2bb3da066c..394066aa5a86 100644
--- a/drivers/char/lrng/Kconfig
+++ b/drivers/char/lrng/Kconfig
@@ -159,4 +159,20 @@ config LRNG_APT_CUTOFF
 	default 325 if !LRNG_APT_BROKEN
 	default 32 if LRNG_APT_BROKEN
 
+config LRNG_TESTING
+	bool "Enable entropy test interface to LRNG noise source"
+	depends on DEBUG_FS
+	help
+	  The test interface allows a privileged process to capture
+	  the raw unconditioned noise that is collected by the LRNG
+	  for statistical analysis. Extracted noise data is not used
+	  to seed the LRNG.
+
+	  The raw noise data can be obtained using the lrng_raw
+	  debugfs file. Using the option lrng_testing.boot_test=1
+	  the raw noise of the first 1000 entropy events since boot
+	  can be sampled.
+
+	  If unsure, say N.
+
 endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index c3008763dd14..b2ce1979dc4b 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -15,3 +15,4 @@ obj-$(CONFIG_LRNG_DRBG)		+= lrng_drbg.o
 obj-$(CONFIG_LRNG_KCAPI)	+= lrng_kcapi.o
 obj-$(CONFIG_LRNG_JENT)		+= lrng_jent.o
 obj-$(CONFIG_LRNG_HEALTH_TESTS)	+= lrng_health.o
+obj-$(CONFIG_LRNG_TESTING)	+= lrng_testing.o
diff --git a/drivers/char/lrng/lrng_testing.c b/drivers/char/lrng/lrng_testing.c
new file mode 100644
index 000000000000..0e287eccd622
--- /dev/null
+++ b/drivers/char/lrng/lrng_testing.c
@@ -0,0 +1,271 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * Linux Random Number Generator (LRNG) Raw entropy collection tool
+ *
+ * Copyright (C) 2019 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/atomic.h>
+#include <linux/bug.h>
+#include <linux/debugfs.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/sched/signal.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+#include <linux/workqueue.h>
+#include <asm/errno.h>
+
+#include "lrng_internal.h"
+
+#define LRNG_TESTING_RINGBUFFER_SIZE	1024
+#define LRNG_TESTING_RINGBUFFER_MASK	(LRNG_TESTING_RINGBUFFER_SIZE - 1)
+
+static u32 lrng_testing_rb[LRNG_TESTING_RINGBUFFER_SIZE];
+static u32 lrng_rb_reader = 0;
+static u32 lrng_rb_writer = 0;
+static atomic_t lrng_testing_enabled = ATOMIC_INIT(0);
+
+static DECLARE_WAIT_QUEUE_HEAD(lrng_raw_read_wait);
+static DEFINE_SPINLOCK(lrng_raw_lock);
+
+/*
+ * 0 ==> No boot test, gathering of runtime data allowed
+ * 1 ==> Boot test enabled and ready for collecting data, gathering runtime
+ *	 data is disabled
+ * 2 ==> Boot test completed and disabled, gathering of runtime data is
+ *	 disabled
+ */
+static u32 boot_test = 0;
+module_param(boot_test, uint, 0644);
+MODULE_PARM_DESC(boot_test, "Enable gathering boot time entropy of the first"
+			    " entropy events");
+
+static inline void lrng_raw_entropy_reset(void)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&lrng_raw_lock, flags);
+	lrng_rb_reader = 0;
+	lrng_rb_writer = 0;
+	spin_unlock_irqrestore(&lrng_raw_lock, flags);
+}
+
+static void lrng_raw_entropy_init(void)
+{
+	/*
+	 * The boot time testing implies we have a running test. If the
+	 * caller wants to clear it, he has to unset the boot_test flag
+	 * at runtime via sysfs to enable regular runtime testing
+	 */
+	if (boot_test)
+		return;
+
+	lrng_raw_entropy_reset();
+	atomic_set(&lrng_testing_enabled, 1);
+	pr_warn("Enabling raw entropy collection\n");
+}
+
+static void lrng_raw_entropy_fini(void)
+{
+	if (boot_test)
+		return;
+
+	atomic_set(&lrng_testing_enabled, 0);
+	lrng_raw_entropy_reset();
+	pr_warn("Disabling raw entropy collection\n");
+}
+
+bool lrng_raw_entropy_store(u32 value)
+{
+	unsigned long flags;
+
+	if (!atomic_read(&lrng_testing_enabled) && (boot_test != 1))
+		return false;
+
+	spin_lock_irqsave(&lrng_raw_lock, flags);
+
+	/*
+	 * Disable entropy testing for boot time testing after ring buffer
+	 * is filled.
+	 */
+	if (boot_test) {
+		if (lrng_rb_writer > LRNG_TESTING_RINGBUFFER_SIZE) {
+			boot_test = 2;
+			pr_warn_once("Boot time entropy collection test "
+				     "disabled\n");
+			spin_unlock_irqrestore(&lrng_raw_lock, flags);
+			return false;
+		}
+
+		if (lrng_rb_writer == 1)
+			pr_warn("Boot time entropy collection test enabled\n");
+	}
+
+	lrng_testing_rb[lrng_rb_writer & LRNG_TESTING_RINGBUFFER_MASK] = value;
+	lrng_rb_writer++;
+
+	spin_unlock_irqrestore(&lrng_raw_lock, flags);
+
+	if (wq_has_sleeper(&lrng_raw_read_wait))
+		wake_up_interruptible(&lrng_raw_read_wait);
+
+	return true;
+}
+
+static inline bool lrng_raw_have_data(void)
+{
+	return ((lrng_rb_writer & LRNG_TESTING_RINGBUFFER_MASK) !=
+		 (lrng_rb_reader & LRNG_TESTING_RINGBUFFER_MASK));
+}
+
+static int lrng_raw_entropy_reader(u8 *outbuf, u32 outbuflen)
+{
+	unsigned long flags;
+	int collected_data = 0;
+
+	lrng_raw_entropy_init();
+
+	while (outbuflen) {
+		spin_lock_irqsave(&lrng_raw_lock, flags);
+
+		/* We have no data or reached the writer. */
+		if (!lrng_rb_writer || (lrng_rb_writer == lrng_rb_reader)) {
+
+			spin_unlock_irqrestore(&lrng_raw_lock, flags);
+
+			/*
+			 * Now we gathered all boot data, enable regular data
+			 * collection.
+			 */
+			if (boot_test) {
+				boot_test = 0;
+				goto out;
+			}
+
+			wait_event_interruptible(lrng_raw_read_wait,
+						 lrng_raw_have_data());
+			if (signal_pending(current)) {
+				collected_data = -ERESTARTSYS;
+				goto out;
+			}
+
+			continue;
+		}
+
+		/* We copy out word-wise */
+		if (outbuflen < sizeof(u32)) {
+			spin_unlock_irqrestore(&lrng_raw_lock, flags);
+			goto out;
+		}
+
+		memcpy(outbuf, &lrng_testing_rb[lrng_rb_reader], sizeof(u32));
+		lrng_rb_reader++;
+
+		spin_unlock_irqrestore(&lrng_raw_lock, flags);
+
+		outbuf += sizeof(u32);
+		outbuflen -= sizeof(u32);
+		collected_data += sizeof(u32);
+	}
+
+out:
+	lrng_raw_entropy_fini();
+	return collected_data;
+}
+
+/**************************************************************************
+ * Debugfs interface
+ **************************************************************************/
+static int lrng_raw_extract_user(char __user *buf, size_t nbytes)
+{
+	u8 *tmp, *tmp_aligned;
+	int ret = 0, large_request = (nbytes > 256);
+
+	/*
+	 * The intention of this interface is for collecting at least
+	 * 1000 samples due to the SP800-90B requirements. So, we make no
+	 * effort in avoiding allocating more memory that actually needed
+	 * by the user. Hence, we allocate sufficient memory to always hold
+	 * that amount of data.
+	 */
+	tmp = kmalloc(LRNG_TESTING_RINGBUFFER_SIZE + sizeof(u32), GFP_KERNEL);
+	if (!tmp)
+		return -ENOMEM;
+
+	tmp_aligned = PTR_ALIGN(tmp, sizeof(u32));
+
+	while (nbytes) {
+		int i;
+
+		if (large_request && need_resched()) {
+			if (signal_pending(current)) {
+				if (ret == 0)
+					ret = -ERESTARTSYS;
+				break;
+			}
+			schedule();
+		}
+
+		i = min_t(int, nbytes, LRNG_TESTING_RINGBUFFER_SIZE);
+		i = lrng_raw_entropy_reader(tmp_aligned, i);
+		if (i <= 0) {
+			if (i < 0)
+				ret = i;
+			break;
+		}
+		if (copy_to_user(buf, tmp_aligned, i)) {
+			ret = -EFAULT;
+			break;
+		}
+
+		nbytes -= i;
+		buf += i;
+		ret += i;
+	}
+
+	kzfree(tmp);
+	return ret;
+}
+
+/* DebugFS operations and definition of the debugfs files */
+static ssize_t lrng_raw_read(struct file *file, char __user *to,
+			     size_t count, loff_t *ppos)
+{
+	loff_t pos = *ppos;
+	int ret;
+
+	if (!count)
+		return 0;
+
+	ret = lrng_raw_extract_user(to, count);
+	if (ret < 0)
+		return ret;
+
+	count -= ret;
+	*ppos = pos + count;
+
+	return ret;
+}
+
+static const struct file_operations lrng_raw_name_fops = {
+	.owner = THIS_MODULE,
+	.read = lrng_raw_read,
+};
+
+static int __init lrng_raw_init(void)
+{
+	struct dentry *lrng_raw_debugfs_root;
+
+	lrng_raw_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL);
+	debugfs_create_file_unsafe("lrng_raw", 0400, lrng_raw_debugfs_root,
+				   NULL, &lrng_raw_name_fops);
+
+	return 0;
+}
+
+module_init(lrng_raw_init);
-- 
2.24.1





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v27 12/12] LRNG - add power-on and runtime self-tests
  2020-01-09  8:29     ` [PATCH v27 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                         ` (10 preceding siblings ...)
  2020-01-09  8:35       ` [PATCH v27 11/12] LRNG - add interface for gathering of raw entropy Stephan Müller
@ 2020-01-09  8:35       ` Stephan Müller
  2020-01-10  0:22         ` Randy Dunlap
  2020-01-13 10:39         ` Dan Carpenter
  2020-01-15 10:31       ` [PATCH v28 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
  12 siblings, 2 replies; 162+ messages in thread
From: Stephan Müller @ 2020-01-09  8:35 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap, Julia Lawall

Parts of the LFSR are already covered by self-tests, including:

* Self-test of SP800-90A DRBG provided by the Linux kernel crypto API.

* Self-test of the PRNG provided by the Linux kernel crypto API.

* Raw noise source data testing including SP800-90B compliant
  tests when enabling CONFIG_LRNG_HEALTH_TESTS

This patch adds the self tests for the remaining critical functions of
the LRNG that are essential to maintain entropy and provide
cryptographic strong random numbers. The following self tests are
implemented:

* Self-test of the time array maintenance. This test verifies whether
the time stamp array management to store multiple values in one integer
implements a concatenation of the data.

* Self-test of the LFSR operation. This test injects a monotonic
increasing counter into the LFSR. After completion of the injection of
the counter, 3 pool words are compared with known good values. The known
good values are calculated with the newly-developed tool
lfsr_testvector_generation provided as part of the LRNG test tool set at
[1].

* Self-test of the Hash_DF operation ensures that this function operates
compliant to the specification. The self-test performs a Hash_DF
operation of a zeroized entropy pool state. The test vectors are
generated using the newly-developed tool hash_df_testvector_generation
provided as part of the LRNG test tool set at [1].

* Self-test of the ChaCha20 DRNG is based on the self tests that are
already present and implemented with the stand-alone user space
ChaCha20 DRNG implementation available at [2]. The self-tests cover
different use cases of the DRNG seeded with known seed data.

The status of the LRNG self-tests is provided with the selftest_status
SysFS file. If the file contains a zero, the self-tests passed. The
value 0xffffffff means that the self-tests were not executed. Any other
value indicates a self test failure.

The self-test may be compiled to panic the system if the self-test
fails.

All self tests operate on private state data structures. This implies
that none of the self-tests have any impact on the regular LRNG
operations. This allows the self-tests to be repeated at runtime by
writing anything into the selftest_status SysFS file.

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

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
CC: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
CC: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Kconfig         |  25 ++
 drivers/char/lrng/Makefile        |   1 +
 drivers/char/lrng/lrng_selftest.c | 418 ++++++++++++++++++++++++++++++
 3 files changed, 444 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_selftest.c

diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
index 394066aa5a86..e9827e7df715 100644
--- a/drivers/char/lrng/Kconfig
+++ b/drivers/char/lrng/Kconfig
@@ -175,4 +175,29 @@ config LRNG_TESTING
 
 	  If unsure, say N.
 
+config LRNG_SELFTEST
+	bool "Enable power-on and on-demand self-tests"
+	help
+	  The power-on self tests are executed during boot time
+	  covering the ChaCha20 DRNG, the LFSR processing and the
+	  time stamp management of the LRNG.
+
+	  The on-demand self-tests are triggered by writing any
+	  value into the SysFS file selftest_status. At the same
+	  time, when reading this file, the test status is
+	  returned. A zero indicates that all tests were executed
+	  successfully.
+
+	  If unsure, say Y.
+
+if LRNG_SELFTEST
+
+config LRNG_SELFTEST_PANIC
+	bool "Panic the kernel upon self-test failure"
+	help
+	  If the option is enabled, the kernel is terminated if an
+	  LRNG power-on self-test failure is detected.
+
+endif # LRNG_SELFTEST
+
 endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index b2ce1979dc4b..92219c565f66 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -16,3 +16,4 @@ obj-$(CONFIG_LRNG_KCAPI)	+= lrng_kcapi.o
 obj-$(CONFIG_LRNG_JENT)		+= lrng_jent.o
 obj-$(CONFIG_LRNG_HEALTH_TESTS)	+= lrng_health.o
 obj-$(CONFIG_LRNG_TESTING)	+= lrng_testing.o
+obj-$(CONFIG_LRNG_SELFTEST)	+= lrng_selftest.o
diff --git a/drivers/char/lrng/lrng_selftest.c b/drivers/char/lrng/lrng_selftest.c
new file mode 100644
index 000000000000..9df9b59d9491
--- /dev/null
+++ b/drivers/char/lrng/lrng_selftest.c
@@ -0,0 +1,418 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG power-on and on-demand self test
+ *
+ * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+/*
+ * In addition to the self tests below, the following LRNG components
+ * are covered with self tests during regular operation:
+ *
+ * * power-on self test: SP800-90A DRBG provided by the Linux kernel crypto API
+ * * power-on self test: PRNG provided by the Linux kernel crypto API
+ * * runtime test: Raw noise source data testing including SP800-90B compliant
+ *		   tests when enabling CONFIG_LRNG_HEALTH_TESTS
+ *
+ * Additional developer tests present with LRNG code:
+ * * SP800-90B APT and RCT test enforcement validation when enabling
+ *   CONFIG_LRNG_APT_BROKEN or CONFIG_LRNG_RCT_BROKEN.
+ * * Collection of raw entropy from the interrupt noise source when enabling
+ *   CONFIG_LRNG_TESTING and pulling the data from the kernel with the provided
+ *   interface.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/lrng.h>
+#include <linux/slab.h>
+
+#include "lrng_chacha20.h"
+#include "lrng_internal.h"
+#include "lrng_lfsr.h"
+#include "lrng_sw_noise.h"
+
+#define LRNG_SELFTEST_PASSED		0
+#define LRNG_SEFLTEST_ERROR_TIME	(1 << 0)
+#define LRNG_SEFLTEST_ERROR_LFSR	(1 << 1)
+#define LRNG_SEFLTEST_ERROR_CHACHA20	(1 << 2)
+#define LRNG_SEFLTEST_ERROR_HASHDF	(1 << 3)
+#define LRNG_SELFTEST_NOT_EXECUTED	0xffffffff
+
+static u32 lrng_time_selftest[LRNG_TIME_ARRAY_SIZE];
+
+static unsigned int lrng_selftest_status = LRNG_SELFTEST_NOT_EXECUTED;
+
+static inline void lrng_time_process_selftest_insert(u32 time)
+{
+	static u32 lrng_time_selftest_ptr = 0;
+	u32 ptr = lrng_time_selftest_ptr++ & LRNG_TIME_WORD_MASK;
+
+	lrng_time_selftest[lrng_time_idx2array(ptr)] |=
+		lrng_time_slot_val(time & LRNG_TIME_SLOTSIZE_MASK,
+				   lrng_time_idx2slot(ptr));
+}
+
+static unsigned int lrng_time_process_selftest(void)
+{
+	u32 time;
+	u32 idx_zero_compare = (0 << 0) | (1 << 8) | (2 << 16) | (3 << 24);
+	u32 idx_one_compare  = (4 << 0) | (5 << 8) | (6 << 16) | (7 << 24);
+	u32 idx_last_compare = ((LRNG_TIME_NUM_VALUES - 4) << 0)  |
+			       ((LRNG_TIME_NUM_VALUES - 3) << 8)  |
+			       ((LRNG_TIME_NUM_VALUES - 2) << 16) |
+			       ((LRNG_TIME_NUM_VALUES - 1) << 24);
+
+	(void)idx_one_compare;
+
+	for (time = 0; time < LRNG_TIME_NUM_VALUES; time++)
+		lrng_time_process_selftest_insert(time);
+
+	if ((lrng_time_selftest[0] != idx_zero_compare) ||
+#if (LRNG_TIME_ARRAY_SIZE > 1)
+	    (lrng_time_selftest[1] != idx_one_compare)  ||
+#endif
+	    (lrng_time_selftest[LRNG_TIME_ARRAY_SIZE - 1] != idx_last_compare))
+	{
+		pr_err("LRNG time array self-test FAILED\n");
+		return LRNG_SEFLTEST_ERROR_TIME;
+	}
+
+	return LRNG_SELFTEST_PASSED;
+}
+
+/*
+ * The test vectors are generated with the lfsr_testvector_generation tool
+ * provided as part of the test tool set of the LRNG.
+ */
+static unsigned int lrng_pool_lfsr_selftest(void)
+{
+	/*
+	 * First, 67th and last entry of entropy pool.
+	 *
+	 * The 67th entry is picked because this one is the first to receive
+	 * an entry. As we start with 1 to inject into the LFSR, the
+	 * 67th entry should be equal to rol(1, 7) >> 3 considering that
+	 * all other values of the LFSR are zero and the the twist value of 0
+	 * is applied.
+	 */
+	static u32 const lrng_lfsr_selftest_result[][3] = {
+		{ 0xf56df24a, 0x00000010, 0x0e014939 },
+		{ 0x4b130726, 0x00000010, 0x2802f509 },
+		{ 0x87279152, 0x00000010, 0x00150000 },
+		{ 0x0b67f997, 0x00000010, 0x00150000 },
+		{ 0x4fea174f, 0x00000010, 0xcbf4a6ae },
+		{ 0x77149108, 0x00000010, 0x77bfadf2 },
+		{ 0x1e96037e, 0x00000010, 0x18017e79 },
+		{ 0xc84acef2, 0x00000010, 0x6345f7a8 },
+		{ 0x6a2eb6df, 0x00000010, 0x03950000 },
+	};
+	struct lrng_pool *lrng_pool, *lrng_pool_aligned;
+	u32 i, ret = LRNG_SELFTEST_PASSED;
+
+	BUILD_BUG_ON(ARRAY_SIZE(lrng_lfsr_selftest_result) <
+							CONFIG_LRNG_POOL_SIZE);
+
+	lrng_pool = kzalloc(sizeof(struct lrng_pool) + sizeof(LRNG_KCAPI_ALIGN),
+			    GFP_KERNEL);
+	if (!lrng_pool)
+		return LRNG_SEFLTEST_ERROR_LFSR;
+	lrng_pool_aligned = PTR_ALIGN(lrng_pool, sizeof(u32));
+
+	for (i = 1; i <= LRNG_POOL_SIZE; i++)
+		_lrng_pool_lfsr_u32(lrng_pool_aligned, i);
+
+	if ((atomic_read_u32(&lrng_pool_aligned->pool[0]) !=
+	     lrng_lfsr_selftest_result[CONFIG_LRNG_POOL_SIZE][0]) ||
+	    (atomic_read_u32(&lrng_pool_aligned->pool[67 &
+						      (LRNG_POOL_SIZE - 1)]) !=
+	     lrng_lfsr_selftest_result[CONFIG_LRNG_POOL_SIZE][1]) ||
+	    (atomic_read_u32(&lrng_pool_aligned->pool[LRNG_POOL_SIZE - 1]) !=
+	     lrng_lfsr_selftest_result[CONFIG_LRNG_POOL_SIZE][2])) {
+		pr_err("LRNG LFSR self-test FAILED\n");
+		ret = LRNG_SEFLTEST_ERROR_LFSR;
+	}
+
+	kfree(lrng_pool);
+	return ret;
+}
+
+/*
+ * The test vectors are generated with the hash_df_testvector_generation tool
+ * provided as part of the test tool set of the LRNG.
+ */
+static unsigned int lrng_hash_df_selftest(void)
+{
+	const struct lrng_crypto_cb *crypto_cb = &lrng_cc20_crypto_cb;
+
+	/*
+	 * The size of 45 bytes is chosen arbitrarily. Yet, this size should
+	 * ensure that we have at least two hash blocks plus some fraction
+	 * of a hash block generated.
+	 */
+	static u8 const lrng_hash_df_selftest_result[][45] = {
+		{
+			0x3b, 0xbe, 0x7a, 0xbd, 0x2b, 0x16, 0x02, 0x4c,
+			0xfc, 0xd3, 0x02, 0x15, 0xf0, 0x86, 0xd4, 0xdb,
+			0x49, 0xec, 0x26, 0x53, 0xd6, 0xc9, 0x6d, 0xad,
+			0x24, 0xca, 0x72, 0x89, 0x2c, 0xfa, 0x48, 0x18,
+			0xf7, 0x47, 0xb5, 0x2f, 0x92, 0xa2, 0x1b, 0xd9,
+			0x24, 0xa7, 0x2f, 0xa2, 0x0b,
+		}, {
+			0xd2, 0xaa, 0xf9, 0x76, 0x26, 0xc6, 0x13, 0xea,
+			0xb8, 0xde, 0xe6, 0x88, 0x8f, 0xc4, 0x7a, 0x7d,
+			0x9c, 0xb4, 0x1b, 0xd1, 0xd1, 0x8a, 0x40, 0xc9,
+			0xaa, 0x45, 0xa6, 0xb6, 0xb5, 0x6f, 0xf6, 0xbc,
+			0xbb, 0x77, 0x37, 0xbc, 0x5a, 0x2d, 0xcc, 0x84,
+			0x25, 0x68, 0x5e, 0xba, 0x16,
+		}, {
+			0x58, 0x66, 0x82, 0x88, 0x29, 0x19, 0xa4, 0xbb,
+			0x33, 0x42, 0xc9, 0x72, 0x0d, 0x68, 0x6e, 0xb9,
+			0xc6, 0xe0, 0x7a, 0xf9, 0x20, 0xca, 0x6d, 0x18,
+			0x35, 0xec, 0xfa, 0x9e, 0xf6, 0x3a, 0xa7, 0xb6,
+			0x92, 0x7a, 0xe5, 0xcd, 0xc5, 0x13, 0x9f, 0x65,
+			0x6a, 0xe1, 0xe4, 0x3f, 0xb9,
+		}, {
+			0xdd, 0xf1, 0x34, 0xca, 0x08, 0xe3, 0xce, 0x8a,
+			0x26, 0x6b, 0xce, 0x99, 0x8a, 0x84, 0xd2, 0x21,
+			0x98, 0x10, 0x95, 0x5f, 0x9f, 0xc3, 0xf2, 0xe4,
+			0x79, 0x75, 0xb5, 0x15, 0xa7, 0xa2, 0xf1, 0xc4,
+			0xdc, 0x67, 0xcb, 0x67, 0x8c, 0xb2, 0x1b, 0xd5,
+			0xd6, 0x8b, 0xc2, 0x34, 0xd6,
+		}, {
+			0xc3, 0x16, 0x9d, 0xf0, 0x78, 0x15, 0xab, 0xf2,
+			0x2f, 0xc9, 0x2e, 0xe1, 0xc6, 0x5e, 0xfa, 0x03,
+			0xaf, 0xd4, 0xd5, 0x47, 0x2a, 0xe8, 0x06, 0xe8,
+			0x7e, 0x0a, 0x71, 0xc7, 0x0d, 0x39, 0xb1, 0xa9,
+			0x5a, 0x49, 0xee, 0x8b, 0x2f, 0xcd, 0xea, 0x96,
+			0xcc, 0x08, 0x71, 0xef, 0x9c,
+		}, {
+			0x1a, 0x3d, 0x70, 0x39, 0xc2, 0x02, 0x4d, 0x3a,
+			0xaa, 0x14, 0x20, 0x88, 0x96, 0x4c, 0x7c, 0xe4,
+			0xaa, 0x49, 0x89, 0x30, 0x50, 0x96, 0xb6, 0xa7,
+			0x55, 0x0a, 0xf8, 0xd2, 0x4e, 0x83, 0x9d, 0x1f,
+			0x56, 0x49, 0x13, 0xc6, 0x46, 0x55, 0x73, 0x0d,
+			0x74, 0xcd, 0x81, 0xe0, 0x65,
+		}, {
+			0x4b, 0xf6, 0x49, 0x89, 0x2a, 0x9f, 0x67, 0xd7,
+			0xb8, 0x1d, 0xbb, 0x5d, 0xf0, 0x1b, 0x60, 0xb6,
+			0xb7, 0xf3, 0x86, 0x6d, 0xe0, 0x04, 0xa1, 0xbc,
+			0x3b, 0xb0, 0x10, 0x91, 0xe8, 0x22, 0x67, 0x5b,
+			0xe8, 0xf0, 0x4f, 0x82, 0x70, 0xc7, 0xe1, 0xc8,
+			0xd8, 0xad, 0x70, 0xcf, 0xf6,
+		}, {
+			0x60, 0x1f, 0x71, 0x07, 0x92, 0xae, 0xa0, 0x24,
+			0xb6, 0xa4, 0x10, 0x70, 0x1f, 0x94, 0x51, 0x9a,
+			0x5a, 0x81, 0xc4, 0x46, 0x78, 0x56, 0x71, 0xdd,
+			0x45, 0x63, 0x01, 0x34, 0x87, 0x79, 0xb4, 0xd5,
+			0x91, 0x79, 0xb9, 0x93, 0x11, 0x44, 0x50, 0xad,
+			0x64, 0x7e, 0x5c, 0xec, 0x16,
+		}, {
+			0x49, 0x2f, 0xa0, 0x45, 0xf8, 0xb0, 0x80, 0x88,
+			0x79, 0xeb, 0xb6, 0x82, 0x1c, 0xf3, 0x67, 0xc4,
+			0x88, 0x88, 0xe9, 0x75, 0x20, 0x54, 0x78, 0xc6,
+			0x5c, 0x59, 0xcf, 0xd9, 0x73, 0x12, 0x17, 0xf4,
+			0x30, 0x9c, 0xb7, 0x21, 0x45, 0xe2, 0xb6, 0x0c,
+			0x0c, 0xeb, 0x1b, 0xdc, 0xdc,
+		}
+	};
+	struct lrng_pool *lrng_pool, *lrng_pool_aligned;
+	u8 hash_df[sizeof(lrng_hash_df_selftest_result[0])]
+							__aligned(sizeof(u32));
+	u32 generated;
+	int ret = 0;
+
+	BUILD_BUG_ON(ARRAY_SIZE(lrng_hash_df_selftest_result) <
+							CONFIG_LRNG_POOL_SIZE);
+
+	lrng_pool = kzalloc(sizeof(struct lrng_pool) + sizeof(LRNG_KCAPI_ALIGN),
+			    GFP_KERNEL);
+	if (!lrng_pool)
+		return LRNG_SEFLTEST_ERROR_HASHDF;
+	lrng_pool_aligned = PTR_ALIGN(lrng_pool, sizeof(u32));
+
+	generated = __lrng_pool_hash_df(crypto_cb, NULL, lrng_pool_aligned,
+					hash_df, sizeof(hash_df) << 3);
+
+	if ((generated >> 3) != sizeof(hash_df) ||
+	    memcmp(hash_df, lrng_hash_df_selftest_result[CONFIG_LRNG_POOL_SIZE],
+		   sizeof(hash_df))) {
+		pr_err("LRNG Hash DF self-test FAILED\n");
+		ret = LRNG_SEFLTEST_ERROR_HASHDF;
+	}
+
+	kfree(lrng_pool);
+	return ret;
+}
+
+/*
+ * The test vectors were generated using the ChaCha20 DRNG from
+ * https://www.chronox.de/chacha20.html
+ */
+static unsigned int lrng_chacha20_drng_selftest(void)
+{
+	const struct lrng_crypto_cb *crypto_cb = &lrng_cc20_crypto_cb;
+	static u8 const seed[CHACHA_KEY_SIZE * 2] = {
+		0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+		0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+		0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+		0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+		0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+		0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+		0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+		0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+	};
+	struct chacha20_block chacha20;
+	int ret;
+	u8 outbuf[CHACHA_KEY_SIZE * 2] __aligned(sizeof(u32));
+
+	/*
+	 * Expected result when ChaCha20 DRNG state is zero:
+	 *	* constants are set to "expand 32-byte k"
+	 *	* remaining state is 0
+	 * and pulling one half ChaCha20 DRNG block.
+	 */
+	static u8 const expected_halfblock[CHACHA_KEY_SIZE] = {
+		0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
+		0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
+		0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
+		0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7 };
+
+	/*
+	 * Expected result when ChaCha20 DRNG state is zero:
+	 *	* constants are set to "expand 32-byte k"
+	 *	* remaining state is 0
+	 * followed by a reseed with two keyblocks
+	 *	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+	 *	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+	 *	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+	 *	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+	 *	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+	 *	0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+	 *	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+	 *	0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f
+	 * and pulling one ChaCha20 DRNG block.
+	 */
+	static u8 const expected_oneblock[CHACHA_KEY_SIZE * 2] = {
+		0xf5, 0xb4, 0xb6, 0x5a, 0xec, 0xcd, 0x5a, 0x65,
+		0x87, 0x56, 0xe3, 0x86, 0x51, 0x54, 0xfc, 0x90,
+		0x56, 0xff, 0x5e, 0xae, 0x58, 0xf2, 0x01, 0x88,
+		0xb1, 0x7e, 0xb8, 0x2e, 0x17, 0x9a, 0x27, 0xe6,
+		0x86, 0xb3, 0xed, 0x33, 0xf7, 0xb9, 0x06, 0x05,
+		0x8a, 0x2d, 0x1a, 0x93, 0xc9, 0x0b, 0x80, 0x04,
+		0x03, 0xaa, 0x60, 0xaf, 0xd5, 0x36, 0x40, 0x11,
+		0x67, 0x89, 0xb1, 0x66, 0xd5, 0x88, 0x62, 0x6d };
+
+	/*
+	 * Expected result when ChaCha20 DRNG state is zero:
+	 *	* constants are set to "expand 32-byte k"
+	 *	* remaining state is 0
+	 * followed by a reseed with one key block plus one byte
+	 *	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+	 *	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+	 *	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+	 *	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+	 *	0x20
+	 * and pulling less than one ChaCha20 DRNG block.
+	 */
+	static u8 const expected_block_nonalinged[CHACHA_KEY_SIZE + 1] = {
+		0x3d, 0x13, 0x47, 0x1e, 0x7f, 0x7c, 0x99, 0x33,
+		0xfc, 0x44, 0xa4, 0xdd, 0xf9, 0x3d, 0xe1, 0x9a,
+		0xd4, 0xe8, 0x7a, 0x7d, 0x42, 0xac, 0xd1, 0xcd,
+		0x10, 0x69, 0xe7, 0xbf, 0xd4, 0xfd, 0x69, 0x4b,
+		0xa7 };
+
+	memset(&chacha20, 0, sizeof(chacha20));
+	lrng_cc20_init_rfc7539(&chacha20);
+
+	/* Generate with zero state */
+	ret = crypto_cb->lrng_drng_generate_helper(&chacha20, outbuf,
+						   sizeof(expected_halfblock));
+	if (ret != sizeof(expected_halfblock))
+		goto err;
+	if (memcmp(outbuf, expected_halfblock, sizeof(expected_halfblock)))
+		goto err;
+
+	/* Clear state of DRNG */
+	memset(&chacha20.key.u[0], 0, 48);
+
+	/* Reseed with 2 key blocks */
+	ret = crypto_cb->lrng_drng_seed_helper(&chacha20, seed,
+					       sizeof(expected_oneblock));
+	if (ret < 0)
+		goto err;
+	ret = crypto_cb->lrng_drng_generate_helper(&chacha20, outbuf,
+						   sizeof(expected_oneblock));
+	if (ret != sizeof(expected_oneblock))
+		goto err;
+	if (memcmp(outbuf, expected_oneblock, sizeof(expected_oneblock)))
+		goto err;
+
+	/* Clear state of DRNG */
+	memset(&chacha20.key.u[0], 0, 48);
+
+	/* Reseed with 1 key block and one byte */
+	ret = crypto_cb->lrng_drng_seed_helper(&chacha20, seed,
+					sizeof(expected_block_nonalinged));
+	if (ret < 0)
+		goto err;
+	ret = crypto_cb->lrng_drng_generate_helper(&chacha20, outbuf,
+					sizeof(expected_block_nonalinged));
+	if (ret != sizeof(expected_block_nonalinged))
+		goto err;
+	if (memcmp(outbuf, expected_block_nonalinged,
+		   sizeof(expected_block_nonalinged)))
+		goto err;
+
+	return LRNG_SELFTEST_PASSED;
+
+err:
+	pr_err("LRNG ChaCha20 DRNG self-test FAILED\n");
+	return LRNG_SEFLTEST_ERROR_CHACHA20;
+}
+
+static int lrng_selftest(void)
+{
+	unsigned int ret = lrng_time_process_selftest();
+
+	ret |= lrng_pool_lfsr_selftest();
+	ret |= lrng_chacha20_drng_selftest();
+	ret |= lrng_hash_df_selftest();
+
+	if (ret) {
+		if (IS_ENABLED(CONFIG_LRNG_SELFTEST_PANIC))
+			panic("LRNG self-tests failed: %u\n", ret);
+	} else {
+		pr_info("LRNG self-tests passed\n");
+	}
+
+	lrng_selftest_status = ret;
+
+	if (lrng_selftest_status)
+		return -EFAULT;
+	return 0;
+}
+
+#ifdef CONFIG_SYSFS
+/* Re-perform self test when any value is written to the sysfs file. */
+static int lrng_selftest_sysfs_set(const char *val,
+				   const struct kernel_param *kp)
+{
+	return lrng_selftest();
+}
+
+static const struct kernel_param_ops lrng_selftest_sysfs = {
+	.set = lrng_selftest_sysfs_set,
+	.get = param_get_uint,
+};
+module_param_cb(selftest_status, &lrng_selftest_sysfs, &lrng_selftest_status,
+		0644);
+#endif	/* CONFIG_SYSFS */
+
+static int __init lrng_selftest_init(void)
+{
+	return lrng_selftest();
+}
+
+module_init(lrng_selftest_init);
-- 
2.24.1





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* Re: [PATCH v27 10/12] LRNG - add SP800-90B compliant health tests
  2020-01-09  8:34       ` [PATCH v27 10/12] LRNG - add SP800-90B compliant health tests Stephan Müller
@ 2020-01-10  0:20         ` Randy Dunlap
  2020-01-10  8:27           ` Stephan Mueller
  0 siblings, 1 reply; 162+ messages in thread
From: Randy Dunlap @ 2020-01-10  0:20 UTC (permalink / raw)
  To: Stephan Müller, Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Julia Lawall

Hi,

On 1/9/20 12:34 AM, Stephan Müller wrote:
> ---
>  drivers/char/lrng/Kconfig       |  56 +++++
>  drivers/char/lrng/Makefile      |   1 +
>  drivers/char/lrng/lrng_health.c | 409 ++++++++++++++++++++++++++++++++
>  3 files changed, 466 insertions(+)
>  create mode 100644 drivers/char/lrng/lrng_health.c
> 
> diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
> index 10b7cbdb8c8e..7b2bb3da066c 100644
> --- a/drivers/char/lrng/Kconfig
> +++ b/drivers/char/lrng/Kconfig
> @@ -103,4 +103,60 @@ config LRNG_JENT
>  	  time or at runtime with the lrng_base.jitterrng configuration
>  	  variable.
>  
> +config LRNG_HEALTH_TESTS
> +	bool "Enable noise source online health tests"
> +	help
> +	  The online health tests validate the noise source at
> +	  runtime for fatal errors. These tests include SP800-90B
> +	  compliant tests which are invoked if the system is booted
> +	  with fips=1. In case of fatal errors during active
> +	  SP800-90B tests, the issue is logged and the noise
> +	  data is discarded. These tests are required for full
> +	  compliance with SP800-90B.
> +
> +	  If unsure, say Y.
> +
> +config LRNG_RCT_BROKEN
> +	bool "SP800-90B RCT with dangerous low cutoff value"
> +	depends on LRNG_HEALTH_TESTS
> +	depends on BROKEN
> +	default n
> +	help
> +	  This option enables a dangerously low SP800-90B repetitive
> +	  count test (RCT) cutoff value which makes it very likely
> +	  that the RCT is triggered to raise a self test failure.

	                                       self-test

> +
> +	  This option is ONLY intended for developers wanting to
> +	  test the effectiveness of the SP800-90B RCT health test.
> +
> +	  If unsure, say N.
> +
> +config LRNG_APT_BROKEN
> +	bool "SP800-90B APT with dangerous low cutoff value"
> +	depends on LRNG_HEALTH_TESTS
> +	depends on BROKEN
> +	default n
> +	help
> +	  This option enables a dangerously low SP800-90B adaptive
> +	  proportion test (APT) cutoff value which makes it very
> +	  likely that the RCT is triggered to raise a self test

	                                              self-test

> +	  failure.
> +
> +	  This option is ONLY intended for developers wanting to
> +	  test the effectiveness of the SP800-90B APT health test.
> +
> +	  If unsure, say N.
> +
> +# Default taken from SP800-90B sec 4.4.1 - significance level 2^-30
> +config LRNG_RCT_CUTOFF
> +	int
> +	default 30 if !LRNG_RCT_BROKEN
> +	default 1 if LRNG_RCT_BROKEN
> +
> +# Default taken from SP800-90B sec 4.4.2 - significance level 2^-30
> +config LRNG_APT_CUTOFF
> +	int
> +	default 325 if !LRNG_APT_BROKEN
> +	default 32 if LRNG_APT_BROKEN
> +
>  endif # LRNG

> diff --git a/drivers/char/lrng/lrng_health.c b/drivers/char/lrng/lrng_health.c
> new file mode 100644
> index 000000000000..da8b42b96918
> --- /dev/null
> +++ b/drivers/char/lrng/lrng_health.c
> @@ -0,0 +1,409 @@
> +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
> +/*
> + * Linux Random Number Generator (LRNG) Health Testing
> + *
> + * Copyright (C) 2019 - 2020, Stephan Mueller <smueller@chronox.de>
> + */

[snip]

> +
> +/***************************************************************************
> + * SP800-90B Compliance
> + *
> + * If the Linux-RNG is booted into FIPS mode, the following interfaces
> + * provide an SP800-90B compliant noise source:
> + *
> + * * /dev/random
> + * * getrandom(2)
> + * * get_random_bytes when using it in conjunction with
> + *   add_random_ready_callback
> + *
> + * All other interfaces, including /dev/urandom or get_random_bytes without
> + * the add_random_ready_callback cannot claim to use an SP800-90B compliant
> + * noise source.
> + ***************************************************************************/
> +
> +/**
> + * Perform SP800-90B startup testing
> + */

/** in the kernel sources means "this is the beginning of a kernel-doc comment block",
but this is not a kernel-doc comment block, so just use /* to begin the comment.

> +static inline void lrng_sp80090b_startup(struct lrng_health *health)
> +{
> +	if (!health->sp80090b_startup_done &&
> +	    atomic_dec_and_test(&health->sp80090b_startup_blocks)) {
> +		health->sp80090b_startup_done = true;
> +		pr_info("SP800-90B startup health tests completed\n");
> +		lrng_init_ops(0);
> +
> +		/*
> +		 * Force a reseed of DRNGs to ensure they are seeded with
> +		 * entropy that passed the SP800-90B health tests.
> +		 * As the DRNG always will reseed before generating
> +		 * random numbers, it does not need a reseed trigger.
> +		 */
> +		lrng_drng_force_reseed();
> +	}
> +}
> +
> +/**
> + * Handle failure of SP800-90B startup testing
> + */

ditto

> +static inline void lrng_sp80090b_startup_failure(struct lrng_health *health)
> +{
> +	/* Reset of LRNG and its entropy - NOTE: we are in atomic context */
> +	lrng_reset();
> +
> +	/*
> +	 * Reset the SP800-90B startup test.
> +	 *
> +	 * NOTE SP800-90B section 4.3 bullet 4 does not specify what
> +	 * exactly is to be done in case of failure! Thus, we do what
> +	 * makes sense, i.e. restarting the health test and thus gating
> +	 * the output function of /dev/random and getrandom(2).
> +	 */
> +	atomic_set(&health->sp80090b_startup_blocks,
> +		   LRNG_SP80090B_STARTUP_BLOCKS);
> +}
> +
> +/**
> + * Handle failure of SP800-90B runtime testing
> + */

ditto

> +static inline void lrng_sp80090b_runtime_failure(struct lrng_health *health)
> +{
> +	lrng_sp80090b_startup_failure(health);
> +	health->sp80090b_startup_done = false;
> +}
> +
> +static inline void lrng_sp80090b_failure(struct lrng_health *health)
> +{
> +	if (health->sp80090b_startup_done) {
> +		pr_err("SP800-90B runtime health test failure - invalidating "
> +		       "all existing entropy and initiate SP800-90B startup\n");
> +		lrng_sp80090b_runtime_failure(health);
> +	} else {
> +		pr_err("SP800-90B startup test failure - resetting\n");
> +		lrng_sp80090b_startup_failure(health);
> +	}
> +}
> +
> +/**
> + * Is the SP800-90B startup testing complete?
> + *
> + * This function is called by the LRNG to determine whether to unblock
> + * a certain user interface. Therefore, only the potentially blocking
> + * user interfaces are considered SP800-90B compliant.
> + */

ditto.

> +bool lrng_sp80090b_startup_complete(void)
> +{
> +	struct lrng_health *health = &lrng_health;
> +
> +	return (lrng_sp80090b_health_enabled()) ? health->sp80090b_startup_done:
> +						  true;
> +}
> +
> +bool lrng_sp80090b_compliant(void)
> +{
> +	struct lrng_health *health = &lrng_health;
> +
> +	return lrng_sp80090b_health_enabled() && health->sp80090b_startup_done;
> +}
> +
> +/***************************************************************************
> + * Adaptive Proportion Test
> + *
> + * This test complies with SP800-90B section 4.4.2.
> + ***************************************************************************/
> +
> +/**
> + * Reset the APT counter
> + *
> + * @health [in] Reference to health state
> + */

ditto

> +static inline void lrng_apt_reset(struct lrng_health *health,
> +				  unsigned int time_masked)
> +{
> +	struct lrng_apt *apt = &health->apt;
> +
> +	pr_debug("APT value %d for base %d\n",
> +		 atomic_read(&apt->apt_count), atomic_read(&apt->apt_base));
> +
> +	/* Reset APT */
> +	atomic_set(&apt->apt_count, 0);
> +	atomic_set(&apt->apt_base, time_masked);
> +}
> +
> +static inline void lrng_apt_restart(struct lrng_health *health)
> +{
> +	struct lrng_apt *apt = &health->apt;
> +
> +	atomic_set(&apt->apt_trigger, LRNG_APT_WINDOW_SIZE);
> +}
> +
> +/**
> + * Insert a new entropy event into APT
> + *
> + * This function does is void as it does not decide about the fate of a time
> + * stamp. An APT failure can only happen at the same time of a stuck test
> + * failure. Thus, the stuck failure will already decide how the time stamp
> + * is handled.
> + *
> + * @health [in] Reference to health state
> + * @now_time [in] Time stamp to process
> + */

ditto
or use complete kernel-doc notation.

> +static inline void lrng_apt_insert(struct lrng_health *health,
> +				   unsigned int now_time)
> +{
> +	struct lrng_apt *apt = &health->apt;
> +
> +	if (!lrng_sp80090b_health_requested())
> +		return;
> +
> +	now_time &= LRNG_APT_WORD_MASK;
> +
> +	/* Initialization of APT */
> +	if (!apt->apt_base_set) {
> +		atomic_set(&apt->apt_base, now_time);
> +		apt->apt_base_set = true;
> +		return;
> +	}
> +
> +	if (now_time == (unsigned int)atomic_read(&apt->apt_base)) {
> +		u32 apt_val = (u32)atomic_inc_return_relaxed(&apt->apt_count);
> +
> +		if (apt_val >= CONFIG_LRNG_APT_CUTOFF)
> +			lrng_sp80090b_failure(health);
> +	}
> +
> +	if (atomic_dec_and_test(&apt->apt_trigger)) {
> +		lrng_apt_restart(health);
> +		lrng_apt_reset(health, now_time);
> +		lrng_sp80090b_startup(health);
> +	}
> +}
> +
> +/***************************************************************************
> + * Repetition Count Test
> + *
> + * The LRNG uses an enhanced version of the Repetition Count Test
> + * (RCT) specified in SP800-90B section 4.4.1. Instead of counting identical
> + * back-to-back values, the input to the RCT is the counting of the stuck
> + * values while filling the entropy pool.
> + *
> + * The RCT is applied with an alpha of 2^-30 compliant to FIPS 140-2 IG 9.8.
> + *
> + * During the counting operation, the LRNG always calculates the RCT
> + * cut-off value of C. If that value exceeds the allowed cut-off value,
> + * the LRNG will invalidate all entropy for the entropy pool which implies
> + * that no data can be extracted from the entropy pool unless new entropy
> + * is received.
> + ***************************************************************************/
> +
> +/**
> + * Hot code path - Insert data for Repetition Count Test
> + *
> + * @health: Reference to health information
> + * @stuck: Decision of stuck test
> + */

ditto

> +static inline void lrng_rct(struct lrng_health *health, int stuck)
> +{
> +	struct lrng_rct *rct = &health->rct;
> +
> +	if (!lrng_sp80090b_health_requested())
> +		return;
> +
> +	if (stuck) {
> +		u32 rct_count = atomic_add_return_relaxed(1, &rct->rct_count);
> +
> +		pr_debug("RCT count: %u\n", rct_count);
> +
> +		/*
> +		 * The cutoff value is based on the following consideration:
> +		 * alpha = 2^-30 as recommended in FIPS 140-2 IG 9.8.
> +		 * In addition, we imply an entropy value H of 1 bit as this
> +		 * is the minimum entropy required to provide full entropy.
> +		 *
> +		 * Note, rct_count (which equals to value B in the
> +		 * pseudo code of SP800-90B section 4.4.1) starts with zero.
> +		 * Hence we need to subtract one from the cutoff value as
> +		 * calculated following SP800-90B.
> +		 */
> +		if (rct_count >= CONFIG_LRNG_RCT_CUTOFF) {
> +			atomic_set(&rct->rct_count, 0);
> +
> +			/*
> +			 * APT must start anew as we consider all previously
> +			 * recorded data to contain no entropy.
> +			 */
> +			lrng_apt_restart(health);
> +
> +			lrng_sp80090b_failure(health);
> +		}
> +	} else {
> +		atomic_set(&rct->rct_count, 0);
> +	}
> +}
> +
> +/***************************************************************************
> + * Stuck Test
> + *
> + * Checking the:
> + *      1st derivative of the event occurrence (time delta)
> + *      2nd derivative of the event occurrence (delta of time deltas)
> + *      3rd derivative of the event occurrence (delta of delta of time deltas)
> + *
> + * All values must always be non-zero. The stuck test is only valid disabled if
> + * high-resolution time stamps are identified after initialization.
> + ***************************************************************************/
> +
> +static inline u32 lrng_delta(u32 prev, u32 next)
> +{
> +	/*
> +	 * Note that this (unsigned) subtraction does yield the correct value
> +	 * in the wraparound-case, i.e. when next < prev.
> +	 */
> +	return (next - prev);
> +}
> +
> +/**
> + * Hot code path
> + *
> + * @health: Reference to health information
> + * @now: Event time
> + * @return: 0 event occurrence not stuck (good time stamp)
> + *	    != 0 event occurrence stuck (reject time stamp)
> + */

ditto

> +static inline int lrng_irq_stuck(struct lrng_stuck_test *stuck, u32 now_time)
> +{
> +	u32 delta = lrng_delta(stuck->last_time, now_time);
> +	u32 delta2 = lrng_delta(stuck->last_delta, delta);
> +	u32 delta3 = lrng_delta(stuck->last_delta2, delta2);
> +
> +	stuck->last_time = now_time;
> +	stuck->last_delta = delta;
> +	stuck->last_delta2 = delta2;
> +
> +	if (!delta || !delta2 || !delta3)
> +		return 1;
> +
> +	return 0;
> +}
> +
> +/***************************************************************************
> + * Health test interfaces
> + ***************************************************************************/
> +
> +/**
> + * Disable all health tests
> + */

ditto

> +void lrng_health_disable(void)
> +{
> +	struct lrng_health *health = &lrng_health;
> +
> +	health->health_test_enabled = false;
> +
> +	if (lrng_sp80090b_health_requested())
> +		pr_warn("SP800-90B compliance requested but the Linux RNG is "
> +			"NOT SP800-90B compliant\n");
> +}
> +
> +/**
> + * Hot code path - Perform health test on time stamp received from an event
> + *
> + * @now_time Time stap
> + */

ditto

> +enum lrng_health_res lrng_health_test(u32 now_time)
> +{


Thanks.
-- 
~Randy


^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v27 12/12] LRNG - add power-on and runtime self-tests
  2020-01-09  8:35       ` [PATCH v27 12/12] LRNG - add power-on and runtime self-tests Stephan Müller
@ 2020-01-10  0:22         ` Randy Dunlap
  2020-01-10  7:48           ` Stephan Mueller
  2020-01-13 10:39         ` Dan Carpenter
  1 sibling, 1 reply; 162+ messages in thread
From: Randy Dunlap @ 2020-01-10  0:22 UTC (permalink / raw)
  To: Stephan Müller, Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Julia Lawall

Hi,

On 1/9/20 12:35 AM, Stephan Müller wrote:

> ---
>  drivers/char/lrng/Kconfig         |  25 ++
>  drivers/char/lrng/Makefile        |   1 +
>  drivers/char/lrng/lrng_selftest.c | 418 ++++++++++++++++++++++++++++++
>  3 files changed, 444 insertions(+)
>  create mode 100644 drivers/char/lrng/lrng_selftest.c
> 
> diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
> index 394066aa5a86..e9827e7df715 100644
> --- a/drivers/char/lrng/Kconfig
> +++ b/drivers/char/lrng/Kconfig
> @@ -175,4 +175,29 @@ config LRNG_TESTING
>  
>  	  If unsure, say N.
>  
> +config LRNG_SELFTEST
> +	bool "Enable power-on and on-demand self-tests"
> +	help
> +	  The power-on self tests are executed during boot time

	               self-tests

> +	  covering the ChaCha20 DRNG, the LFSR processing and the
> +	  time stamp management of the LRNG.
> +
> +	  The on-demand self-tests are triggered by writing any
> +	  value into the SysFS file selftest_status. At the same
> +	  time, when reading this file, the test status is
> +	  returned. A zero indicates that all tests were executed
> +	  successfully.
> +
> +	  If unsure, say Y.
> +
> +if LRNG_SELFTEST
> +
> +config LRNG_SELFTEST_PANIC
> +	bool "Panic the kernel upon self-test failure"
> +	help
> +	  If the option is enabled, the kernel is terminated if an
> +	  LRNG power-on self-test failure is detected.
> +
> +endif # LRNG_SELFTEST
> +
>  endif # LRNG


-- 
~Randy


^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v27 09/12] LRNG - add Jitter RNG fast noise source
  2020-01-09  8:34       ` [PATCH v27 09/12] LRNG - add Jitter RNG fast noise source Stephan Müller
@ 2020-01-10  0:24         ` Randy Dunlap
  2020-01-10  7:45           ` Stephan Mueller
  0 siblings, 1 reply; 162+ messages in thread
From: Randy Dunlap @ 2020-01-10  0:24 UTC (permalink / raw)
  To: Stephan Müller, Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Julia Lawall

Hi,

On 1/9/20 12:34 AM, Stephan Müller wrote:

> ---
>  drivers/char/lrng/Kconfig     | 11 +++++
>  drivers/char/lrng/Makefile    |  1 +
>  drivers/char/lrng/lrng_jent.c | 87 +++++++++++++++++++++++++++++++++++
>  3 files changed, 99 insertions(+)
>  create mode 100644 drivers/char/lrng/lrng_jent.c
> 

> diff --git a/drivers/char/lrng/lrng_jent.c b/drivers/char/lrng/lrng_jent.c
> new file mode 100644
> index 000000000000..97c0d192e9c8
> --- /dev/null
> +++ b/drivers/char/lrng/lrng_jent.c
> @@ -0,0 +1,87 @@
> +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
> +/*
> + * LRNG Fast Noise Source: Jitter RNG
> + *
> + * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
> + */
> +
> +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> +
> +#include <linux/types.h>
> +#include <crypto/internal/jitterentropy.h>
> +
> +#include "lrng_internal.h"
> +
> +/*
> + * Estimated entropy of data is a 16th of LRNG_DRNG_SECURITY_STRENGTH_BITS.
> + * Albeit a full entropy assessment is provided for the noise source indicating
> + * that it provides high entropy rates and considering that it deactivates
> + * when it detects insufficient hardware, the chosen under estimation of
> + * entropy is considered to be acceptable to all reviewers.
> + */
> +static u32 jitterrng = LRNG_DRNG_SECURITY_STRENGTH_BITS>>4;
> +module_param(jitterrng, uint, 0644);
> +MODULE_PARM_DESC(jitterrng, "Entropy in bits of 256 data bits from Jitter "
> +			    "RNG noise source");
> +
> +/**
> + * Get Jitter RNG entropy
> + *
> + * @outbuf buffer to store entropy
> + * @outbuflen length of buffer
> + * @return > 0 on success where value provides the added entropy in bits
> + *	   0 if no fast source was available
> + */

Don't begin the comment block with /**
or convert it to Linux kernel-doc notation format.

> +static struct rand_data *lrng_jent_state;
> +
> +u32 lrng_get_jent(u8 *outbuf, unsigned int outbuflen)
> +{
> +	int ret;
> +	u32 ent_bits = jitterrng;
> +	unsigned long flags;
> +	static DEFINE_SPINLOCK(lrng_jent_lock);
> +	static int lrng_jent_initialized = 0;
> +
> +	spin_lock_irqsave(&lrng_jent_lock, flags);
> +
> +	if (!ent_bits || (lrng_jent_initialized == -1)) {
> +		spin_unlock_irqrestore(&lrng_jent_lock, flags);
> +		return 0;
> +	}
> +
> +	if (!lrng_jent_initialized) {
> +		lrng_jent_state = jent_lrng_entropy_collector();
> +		if (!lrng_jent_state) {
> +			jitterrng = 0;
> +			lrng_jent_initialized = -1;
> +			spin_unlock_irqrestore(&lrng_jent_lock, flags);
> +			pr_info("Jitter RNG unusable on current system\n");
> +			return 0;
> +		}
> +		lrng_jent_initialized = 1;
> +		pr_debug("Jitter RNG working on current system\n");
> +	}
> +	ret = jent_read_entropy(lrng_jent_state, outbuf, outbuflen);
> +	spin_unlock_irqrestore(&lrng_jent_lock, flags);
> +
> +	if (ret) {
> +		pr_debug("Jitter RNG failed with %d\n", ret);
> +		return 0;
> +	}
> +
> +	/* Obtain entropy statement */
> +	if (outbuflen != LRNG_DRNG_SECURITY_STRENGTH_BYTES)
> +		ent_bits = (ent_bits * outbuflen<<3) /
> +			   LRNG_DRNG_SECURITY_STRENGTH_BITS;
> +	/* Cap entropy to buffer size in bits */
> +	ent_bits = min_t(u32, ent_bits, outbuflen<<3);
> +	pr_debug("obtained %u bits of entropy from Jitter RNG noise source\n",
> +		 ent_bits);
> +
> +	return ent_bits;
> +}
> +
> +u32 lrng_jent_entropylevel(void)
> +{
> +	return min_t(u32, jitterrng, LRNG_DRNG_SECURITY_STRENGTH_BITS);
> +}
> 

thanks.
-- 
~Randy


^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v27 09/12] LRNG - add Jitter RNG fast noise source
  2020-01-10  0:24         ` Randy Dunlap
@ 2020-01-10  7:45           ` Stephan Mueller
  0 siblings, 0 replies; 162+ messages in thread
From: Stephan Mueller @ 2020-01-10  7:45 UTC (permalink / raw)
  To: Randy Dunlap
  Cc: Arnd Bergmann, Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Julia Lawall

Am Freitag, 10. Januar 2020, 01:24:47 CET schrieb Randy Dunlap:

Hi Randy,

> Hi,
> 
> On 1/9/20 12:34 AM, Stephan Müller wrote:
> > ---
> > 
> >  drivers/char/lrng/Kconfig     | 11 +++++
> >  drivers/char/lrng/Makefile    |  1 +
> >  drivers/char/lrng/lrng_jent.c | 87 +++++++++++++++++++++++++++++++++++
> >  3 files changed, 99 insertions(+)
> >  create mode 100644 drivers/char/lrng/lrng_jent.c
> > 
> > diff --git a/drivers/char/lrng/lrng_jent.c b/drivers/char/lrng/lrng_jent.c
> > new file mode 100644
> > index 000000000000..97c0d192e9c8
> > --- /dev/null
> > +++ b/drivers/char/lrng/lrng_jent.c
> > @@ -0,0 +1,87 @@
> > +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
> > +/*
> > + * LRNG Fast Noise Source: Jitter RNG
> > + *
> > + * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
> > + */
> > +
> > +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> > +
> > +#include <linux/types.h>
> > +#include <crypto/internal/jitterentropy.h>
> > +
> > +#include "lrng_internal.h"
> > +
> > +/*
> > + * Estimated entropy of data is a 16th of
> > LRNG_DRNG_SECURITY_STRENGTH_BITS. + * Albeit a full entropy assessment is
> > provided for the noise source indicating + * that it provides high
> > entropy rates and considering that it deactivates + * when it detects
> > insufficient hardware, the chosen under estimation of + * entropy is
> > considered to be acceptable to all reviewers.
> > + */
> > +static u32 jitterrng = LRNG_DRNG_SECURITY_STRENGTH_BITS>>4;
> > +module_param(jitterrng, uint, 0644);
> > +MODULE_PARM_DESC(jitterrng, "Entropy in bits of 256 data bits from Jitter
> > " +			    "RNG noise source");
> > +
> > +/**
> > + * Get Jitter RNG entropy
> > + *
> > + * @outbuf buffer to store entropy
> > + * @outbuflen length of buffer
> > + * @return > 0 on success where value provides the added entropy in bits
> > + *	   0 if no fast source was available
> > + */
> 
> Don't begin the comment block with /**
> or convert it to Linux kernel-doc notation format.

Yes, the colons are missing and there is no @return. It will be fixed with the 
next patch set.

Thank you.
> 
> > +static struct rand_data *lrng_jent_state;
> > +
> > +u32 lrng_get_jent(u8 *outbuf, unsigned int outbuflen)
> > +{
> > +	int ret;
> > +	u32 ent_bits = jitterrng;
> > +	unsigned long flags;
> > +	static DEFINE_SPINLOCK(lrng_jent_lock);
> > +	static int lrng_jent_initialized = 0;
> > +
> > +	spin_lock_irqsave(&lrng_jent_lock, flags);
> > +
> > +	if (!ent_bits || (lrng_jent_initialized == -1)) {
> > +		spin_unlock_irqrestore(&lrng_jent_lock, flags);
> > +		return 0;
> > +	}
> > +
> > +	if (!lrng_jent_initialized) {
> > +		lrng_jent_state = jent_lrng_entropy_collector();
> > +		if (!lrng_jent_state) {
> > +			jitterrng = 0;
> > +			lrng_jent_initialized = -1;
> > +			spin_unlock_irqrestore(&lrng_jent_lock, flags);
> > +			pr_info("Jitter RNG unusable on current system\n");
> > +			return 0;
> > +		}
> > +		lrng_jent_initialized = 1;
> > +		pr_debug("Jitter RNG working on current system\n");
> > +	}
> > +	ret = jent_read_entropy(lrng_jent_state, outbuf, outbuflen);
> > +	spin_unlock_irqrestore(&lrng_jent_lock, flags);
> > +
> > +	if (ret) {
> > +		pr_debug("Jitter RNG failed with %d\n", ret);
> > +		return 0;
> > +	}
> > +
> > +	/* Obtain entropy statement */
> > +	if (outbuflen != LRNG_DRNG_SECURITY_STRENGTH_BYTES)
> > +		ent_bits = (ent_bits * outbuflen<<3) /
> > +			   LRNG_DRNG_SECURITY_STRENGTH_BITS;
> > +	/* Cap entropy to buffer size in bits */
> > +	ent_bits = min_t(u32, ent_bits, outbuflen<<3);
> > +	pr_debug("obtained %u bits of entropy from Jitter RNG noise source\n",
> > +		 ent_bits);
> > +
> > +	return ent_bits;
> > +}
> > +
> > +u32 lrng_jent_entropylevel(void)
> > +{
> > +	return min_t(u32, jitterrng, LRNG_DRNG_SECURITY_STRENGTH_BITS);
> > +}
> 
> thanks.



Ciao
Stephan



^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v27 12/12] LRNG - add power-on and runtime self-tests
  2020-01-10  0:22         ` Randy Dunlap
@ 2020-01-10  7:48           ` Stephan Mueller
  0 siblings, 0 replies; 162+ messages in thread
From: Stephan Mueller @ 2020-01-10  7:48 UTC (permalink / raw)
  To: Randy Dunlap
  Cc: Arnd Bergmann, Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Julia Lawall

Am Freitag, 10. Januar 2020, 01:22:51 CET schrieb Randy Dunlap:

Hi Randy,

> Hi,
> 
> On 1/9/20 12:35 AM, Stephan Müller wrote:
> > ---
> > 
> >  drivers/char/lrng/Kconfig         |  25 ++
> >  drivers/char/lrng/Makefile        |   1 +
> >  drivers/char/lrng/lrng_selftest.c | 418 ++++++++++++++++++++++++++++++
> >  3 files changed, 444 insertions(+)
> >  create mode 100644 drivers/char/lrng/lrng_selftest.c
> > 
> > diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
> > index 394066aa5a86..e9827e7df715 100644
> > --- a/drivers/char/lrng/Kconfig
> > +++ b/drivers/char/lrng/Kconfig
> > @@ -175,4 +175,29 @@ config LRNG_TESTING
> > 
> >  	  If unsure, say N.
> > 
> > +config LRNG_SELFTEST
> > +	bool "Enable power-on and on-demand self-tests"
> > +	help
> > +	  The power-on self tests are executed during boot time
> 
> 	               self-tests

Fixed in all occurrences. Thank you.
> 
> > +	  covering the ChaCha20 DRNG, the LFSR processing and the
> > +	  time stamp management of the LRNG.
> > +
> > +	  The on-demand self-tests are triggered by writing any
> > +	  value into the SysFS file selftest_status. At the same
> > +	  time, when reading this file, the test status is
> > +	  returned. A zero indicates that all tests were executed
> > +	  successfully.
> > +
> > +	  If unsure, say Y.
> > +
> > +if LRNG_SELFTEST
> > +
> > +config LRNG_SELFTEST_PANIC
> > +	bool "Panic the kernel upon self-test failure"
> > +	help
> > +	  If the option is enabled, the kernel is terminated if an
> > +	  LRNG power-on self-test failure is detected.
> > +
> > +endif # LRNG_SELFTEST
> > +
> > 
> >  endif # LRNG



Ciao
Stephan



^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v27 10/12] LRNG - add SP800-90B compliant health tests
  2020-01-10  0:20         ` Randy Dunlap
@ 2020-01-10  8:27           ` Stephan Mueller
  0 siblings, 0 replies; 162+ messages in thread
From: Stephan Mueller @ 2020-01-10  8:27 UTC (permalink / raw)
  To: Randy Dunlap
  Cc: Arnd Bergmann, Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Julia Lawall

Am Freitag, 10. Januar 2020, 01:20:44 CET schrieb Randy Dunlap:

Hi Randy,

I have removed the two stars in front of each comment.

I have also fixed the respective comments in lrng_interfaces.c, 
lrng_archrandom.c, lrng_chacha20.c, lrng_drng.c, lrng_pool.c, lrng_switch.c, 
lrng_sw_noise.c. In all other files there were no changes needed.

Thank you.


Ciao
Stephan



^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v27 04/12] LRNG - add switchable DRNG support
  2020-01-09  8:32       ` [PATCH v27 04/12] LRNG - add switchable DRNG support Stephan Müller
@ 2020-01-11  7:09         ` kbuild test robot
  2020-01-12 10:12           ` Stephan Müller
  0 siblings, 1 reply; 162+ messages in thread
From: kbuild test robot @ 2020-01-11  7:09 UTC (permalink / raw)
  To: Stephan Müller
  Cc: kbuild-all, Arnd Bergmann, Greg Kroah-Hartman, linux-crypto,
	LKML, linux-api, Eric W. Biederman, Alexander E. Patrakov,
	Ahmed S. Darwish, Theodore Y. Ts'o, Willy Tarreau,
	Matthew Garrett, Vito Caputo, Andreas Dilger, Jan Kara,
	Ray Strode, William Jon McCann, zhangjs, Andy Lutomirski,
	Florian Weimer, Lennart Poettering, Nicolai Stange, Peter,
	Matthias, Marcelo Henrique Cerri, Roman Drahtmueller,
	Neil Horman, Randy Dunlap, Julia Lawall

Hi "Stephan,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on char-misc/char-misc-testing]
[also build test WARNING on cryptodev/master crypto/master v5.5-rc5 next-20200110]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]

url:    https://github.com/0day-ci/linux/commits/Stephan-M-ller/dev-random-a-new-approach-with-full-SP800-90B/20200110-084934
base:   https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git 68faa679b8be1a74e6663c21c3a9d25d32f1c079
reproduce:
        # apt-get install sparse
        # sparse version: v0.6.1-129-g341daf20-dirty
        make ARCH=x86_64 allmodconfig
        make C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__'

If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@intel.com>


sparse warnings: (new ones prefixed by >>)

>> drivers/char/lrng/lrng_internal.h:239:39: sparse: sparse: context imbalance in 'lrng_drng_switch' - unexpected unlock

vim +/lrng_drng_switch +239 drivers/char/lrng/lrng_internal.h

58c283819a1e87 Stephan Müller 2020-01-09  233  
58c283819a1e87 Stephan Müller 2020-01-09  234  /* Unlock the DRNG */
58c283819a1e87 Stephan Müller 2020-01-09  235  static __always_inline void lrng_drng_unlock(struct lrng_drng *drng,
58c283819a1e87 Stephan Müller 2020-01-09  236  					     unsigned long *flags)
58c283819a1e87 Stephan Müller 2020-01-09  237  {
58c283819a1e87 Stephan Müller 2020-01-09  238  	if (lrng_drng_is_atomic(drng))
58c283819a1e87 Stephan Müller 2020-01-09 @239  		spin_unlock_irqrestore(&drng->spin_lock, *flags);
58c283819a1e87 Stephan Müller 2020-01-09  240  	else
58c283819a1e87 Stephan Müller 2020-01-09  241  		mutex_unlock(&drng->lock);
58c283819a1e87 Stephan Müller 2020-01-09  242  }
58c283819a1e87 Stephan Müller 2020-01-09  243  

:::::: The code at line 239 was first introduced by commit
:::::: 58c283819a1e879bc2e30d05720285f9709f7f6d Linux Random Number Generator

:::::: TO: Stephan Müller <smueller@chronox.de>
:::::: CC: 0day robot <lkp@intel.com>

---
0-DAY kernel test infrastructure                 Open Source Technology Center
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org Intel Corporation

^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v27 04/12] LRNG - add switchable DRNG support
  2020-01-11  7:09         ` kbuild test robot
@ 2020-01-12 10:12           ` Stephan Müller
  0 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2020-01-12 10:12 UTC (permalink / raw)
  To: kbuild test robot
  Cc: kbuild-all, Arnd Bergmann, Greg Kroah-Hartman, linux-crypto,
	LKML, linux-api, Eric W. Biederman, Alexander E. Patrakov,
	Ahmed S. Darwish, Theodore Y. Ts'o, Willy Tarreau,
	Matthew Garrett, Vito Caputo, Andreas Dilger, Jan Kara,
	Ray Strode, William Jon McCann, zhangjs, Andy Lutomirski,
	Florian Weimer, Lennart Poettering, Nicolai Stange, Peter,
	Matthias, Marcelo Henrique Cerri, Roman Drahtmueller,
	Neil Horman, Randy Dunlap, Julia Lawall

Am Samstag, 11. Januar 2020, 08:09:50 CET schrieb kbuild test robot:

Hi,

> Hi "Stephan,
> 
> Thank you for the patch! Perhaps something to improve:
> 
> [auto build test WARNING on char-misc/char-misc-testing]
> [also build test WARNING on cryptodev/master crypto/master v5.5-rc5
> next-20200110] [if your patch is applied to the wrong git tree, please drop
> us a note to help improve the system. BTW, we also suggest to use '--base'
> option to specify the base tree in git format-patch, please see
> https://stackoverflow.com/a/37406982]
> 
> url:   
> https://github.com/0day-ci/linux/commits/Stephan-M-ller/dev-random-a-new-ap
> proach-with-full-SP800-90B/20200110-084934 base:  
> https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git
> 68faa679b8be1a74e6663c21c3a9d25d32f1c079 reproduce:
>         # apt-get install sparse
>         # sparse version: v0.6.1-129-g341daf20-dirty
>         make ARCH=x86_64 allmodconfig
>         make C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__'
> 
> If you fix the issue, kindly add following tag
> Reported-by: kbuild test robot <lkp@intel.com>
> 
> 
> sparse warnings: (new ones prefixed by >>)
> 
> >> drivers/char/lrng/lrng_internal.h:239:39: sparse: sparse: context
> >> imbalance in 'lrng_drng_switch' - unexpected unlock
> vim +/lrng_drng_switch +239 drivers/char/lrng/lrng_internal.h
> 
> 58c283819a1e87 Stephan Müller 2020-01-09  233
> 58c283819a1e87 Stephan Müller 2020-01-09  234  /* Unlock the DRNG */
> 58c283819a1e87 Stephan Müller 2020-01-09  235  static __always_inline void
> lrng_drng_unlock(struct lrng_drng *drng, 58c283819a1e87 Stephan Müller
> 2020-01-09  236  					     unsigned long *flags) 
58c283819a1e87 Stephan
> Müller 2020-01-09  237  {
> 58c283819a1e87 Stephan Müller 2020-01-09  238  	if
> (lrng_drng_is_atomic(drng)) 58c283819a1e87 Stephan Müller 2020-01-09 @239 
> 		spin_unlock_irqrestore(&drng->spin_lock, *flags); 58c283819a1e87 
Stephan
> Müller 2020-01-09  240  	else
> 58c283819a1e87 Stephan Müller 2020-01-09  241  		mutex_unlock(&drng-
>lock);
> 58c283819a1e87 Stephan Müller 2020-01-09  242  }
> 58c283819a1e87 Stephan Müller 2020-01-09  243
> 
> :::::: The code at line 239 was first introduced by commit
> :::::: 58c283819a1e879bc2e30d05720285f9709f7f6d Linux Random Number
> :::::: Generator
> :::::: 
> :::::: TO: Stephan Müller <smueller@chronox.de>
> :::::: CC: 0day robot <lkp@intel.com>
> 
> ---
> 0-DAY kernel test infrastructure                 Open Source Technology
> Center https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org Intel
> Corporation

After analyzing the issue a bit more, it seems that I have to remove 
"unlikely" from lrng_drng_lock which seems to cause additional grief
with sparse. Note, sparse will still report a lock context imbalance as it
used to since we indeed have two lock context as documented in
lrng_drng_switch.

Ciao
Stephan



^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v27 12/12] LRNG - add power-on and runtime self-tests
  2020-01-09  8:35       ` [PATCH v27 12/12] LRNG - add power-on and runtime self-tests Stephan Müller
  2020-01-10  0:22         ` Randy Dunlap
@ 2020-01-13 10:39         ` Dan Carpenter
  2020-01-13 10:46           ` Stephan Mueller
  1 sibling, 1 reply; 162+ messages in thread
From: Dan Carpenter @ 2020-01-13 10:39 UTC (permalink / raw)
  To: kbuild, Stephan Müller
  Cc: kbuild-all, Arnd Bergmann, Greg Kroah-Hartman, linux-crypto,
	LKML, linux-api, Eric W. Biederman, Alexander E. Patrakov,
	Ahmed S. Darwish, Theodore Y. Ts'o, Willy Tarreau,
	Matthew Garrett, Vito Caputo, Andreas Dilger, Jan Kara,
	Ray Strode, William Jon McCann, zhangjs, Andy Lutomirski,
	Florian Weimer, Lennart Poettering, Nicolai Stange, Peter,
	Matthias, Marcelo Henrique Cerri, Roman Drahtmueller,
	Neil Horman, Randy Dunlap, Julia Lawall

Hi "Stephan,

url:    https://github.com/0day-ci/linux/commits/Stephan-M-ller/dev-random-a-new-approach-with-full-SP800-90B/20200110-084934
base:   https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git 68faa679b8be1a74e6663c21c3a9d25d32f1c079

If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@intel.com>
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>

smatch warnings:
drivers/char/lrng/lrng_selftest.c:117 lrng_pool_lfsr_selftest() warn: sizeof(NUMBER)?
drivers/char/lrng/lrng_selftest.c:229 lrng_hash_df_selftest() warn: sizeof(NUMBER)?

# https://github.com/0day-ci/linux/commit/5b6f2811172c968d8eb78167825c58557ea91995
git remote add linux-review https://github.com/0day-ci/linux
git remote update linux-review
git checkout 5b6f2811172c968d8eb78167825c58557ea91995
vim +117 drivers/char/lrng/lrng_selftest.c

5b6f2811172c96 Stephan Müller 2020-01-09   89  static unsigned int lrng_pool_lfsr_selftest(void)
5b6f2811172c96 Stephan Müller 2020-01-09   90  {
5b6f2811172c96 Stephan Müller 2020-01-09   91  	/*
5b6f2811172c96 Stephan Müller 2020-01-09   92  	 * First, 67th and last entry of entropy pool.
5b6f2811172c96 Stephan Müller 2020-01-09   93  	 *
5b6f2811172c96 Stephan Müller 2020-01-09   94  	 * The 67th entry is picked because this one is the first to receive
5b6f2811172c96 Stephan Müller 2020-01-09   95  	 * an entry. As we start with 1 to inject into the LFSR, the
5b6f2811172c96 Stephan Müller 2020-01-09   96  	 * 67th entry should be equal to rol(1, 7) >> 3 considering that
5b6f2811172c96 Stephan Müller 2020-01-09   97  	 * all other values of the LFSR are zero and the the twist value of 0
5b6f2811172c96 Stephan Müller 2020-01-09   98  	 * is applied.
5b6f2811172c96 Stephan Müller 2020-01-09   99  	 */
5b6f2811172c96 Stephan Müller 2020-01-09  100  	static u32 const lrng_lfsr_selftest_result[][3] = {
5b6f2811172c96 Stephan Müller 2020-01-09  101  		{ 0xf56df24a, 0x00000010, 0x0e014939 },
5b6f2811172c96 Stephan Müller 2020-01-09  102  		{ 0x4b130726, 0x00000010, 0x2802f509 },
5b6f2811172c96 Stephan Müller 2020-01-09  103  		{ 0x87279152, 0x00000010, 0x00150000 },
5b6f2811172c96 Stephan Müller 2020-01-09  104  		{ 0x0b67f997, 0x00000010, 0x00150000 },
5b6f2811172c96 Stephan Müller 2020-01-09  105  		{ 0x4fea174f, 0x00000010, 0xcbf4a6ae },
5b6f2811172c96 Stephan Müller 2020-01-09  106  		{ 0x77149108, 0x00000010, 0x77bfadf2 },
5b6f2811172c96 Stephan Müller 2020-01-09  107  		{ 0x1e96037e, 0x00000010, 0x18017e79 },
5b6f2811172c96 Stephan Müller 2020-01-09  108  		{ 0xc84acef2, 0x00000010, 0x6345f7a8 },
5b6f2811172c96 Stephan Müller 2020-01-09  109  		{ 0x6a2eb6df, 0x00000010, 0x03950000 },
5b6f2811172c96 Stephan Müller 2020-01-09  110  	};
5b6f2811172c96 Stephan Müller 2020-01-09  111  	struct lrng_pool *lrng_pool, *lrng_pool_aligned;
5b6f2811172c96 Stephan Müller 2020-01-09  112  	u32 i, ret = LRNG_SELFTEST_PASSED;
5b6f2811172c96 Stephan Müller 2020-01-09  113  
5b6f2811172c96 Stephan Müller 2020-01-09  114  	BUILD_BUG_ON(ARRAY_SIZE(lrng_lfsr_selftest_result) <
5b6f2811172c96 Stephan Müller 2020-01-09  115  							CONFIG_LRNG_POOL_SIZE);
5b6f2811172c96 Stephan Müller 2020-01-09  116  
5b6f2811172c96 Stephan Müller 2020-01-09 @117  	lrng_pool = kzalloc(sizeof(struct lrng_pool) + sizeof(LRNG_KCAPI_ALIGN),
                                                                                               ^^^^^^^^^^^^^^^^^^^^^^^^
Probably just LRNG_KCAPI_ALIGN is intended with no sizeof().

5b6f2811172c96 Stephan Müller 2020-01-09  118  			    GFP_KERNEL);
5b6f2811172c96 Stephan Müller 2020-01-09  119  	if (!lrng_pool)
5b6f2811172c96 Stephan Müller 2020-01-09  120  		return LRNG_SEFLTEST_ERROR_LFSR;
5b6f2811172c96 Stephan Müller 2020-01-09  121  	lrng_pool_aligned = PTR_ALIGN(lrng_pool, sizeof(u32));
5b6f2811172c96 Stephan Müller 2020-01-09  122  
5b6f2811172c96 Stephan Müller 2020-01-09  123  	for (i = 1; i <= LRNG_POOL_SIZE; i++)
5b6f2811172c96 Stephan Müller 2020-01-09  124  		_lrng_pool_lfsr_u32(lrng_pool_aligned, i);
5b6f2811172c96 Stephan Müller 2020-01-09  125  
5b6f2811172c96 Stephan Müller 2020-01-09  126  	if ((atomic_read_u32(&lrng_pool_aligned->pool[0]) !=
5b6f2811172c96 Stephan Müller 2020-01-09  127  	     lrng_lfsr_selftest_result[CONFIG_LRNG_POOL_SIZE][0]) ||
5b6f2811172c96 Stephan Müller 2020-01-09  128  	    (atomic_read_u32(&lrng_pool_aligned->pool[67 &
5b6f2811172c96 Stephan Müller 2020-01-09  129  						      (LRNG_POOL_SIZE - 1)]) !=
5b6f2811172c96 Stephan Müller 2020-01-09  130  	     lrng_lfsr_selftest_result[CONFIG_LRNG_POOL_SIZE][1]) ||
5b6f2811172c96 Stephan Müller 2020-01-09  131  	    (atomic_read_u32(&lrng_pool_aligned->pool[LRNG_POOL_SIZE - 1]) !=
5b6f2811172c96 Stephan Müller 2020-01-09  132  	     lrng_lfsr_selftest_result[CONFIG_LRNG_POOL_SIZE][2])) {
5b6f2811172c96 Stephan Müller 2020-01-09  133  		pr_err("LRNG LFSR self-test FAILED\n");
5b6f2811172c96 Stephan Müller 2020-01-09  134  		ret = LRNG_SEFLTEST_ERROR_LFSR;
5b6f2811172c96 Stephan Müller 2020-01-09  135  	}
5b6f2811172c96 Stephan Müller 2020-01-09  136  
5b6f2811172c96 Stephan Müller 2020-01-09  137  	kfree(lrng_pool);
5b6f2811172c96 Stephan Müller 2020-01-09  138  	return ret;
5b6f2811172c96 Stephan Müller 2020-01-09  139  }
5b6f2811172c96 Stephan Müller 2020-01-09  140  
5b6f2811172c96 Stephan Müller 2020-01-09  141  /*
5b6f2811172c96 Stephan Müller 2020-01-09  142   * The test vectors are generated with the hash_df_testvector_generation tool
5b6f2811172c96 Stephan Müller 2020-01-09  143   * provided as part of the test tool set of the LRNG.
5b6f2811172c96 Stephan Müller 2020-01-09  144   */
5b6f2811172c96 Stephan Müller 2020-01-09  145  static unsigned int lrng_hash_df_selftest(void)
5b6f2811172c96 Stephan Müller 2020-01-09  146  {
5b6f2811172c96 Stephan Müller 2020-01-09  147  	const struct lrng_crypto_cb *crypto_cb = &lrng_cc20_crypto_cb;
5b6f2811172c96 Stephan Müller 2020-01-09  148  
5b6f2811172c96 Stephan Müller 2020-01-09  149  	/*
5b6f2811172c96 Stephan Müller 2020-01-09  150  	 * The size of 45 bytes is chosen arbitrarily. Yet, this size should
5b6f2811172c96 Stephan Müller 2020-01-09  151  	 * ensure that we have at least two hash blocks plus some fraction
5b6f2811172c96 Stephan Müller 2020-01-09  152  	 * of a hash block generated.
5b6f2811172c96 Stephan Müller 2020-01-09  153  	 */
5b6f2811172c96 Stephan Müller 2020-01-09  154  	static u8 const lrng_hash_df_selftest_result[][45] = {
5b6f2811172c96 Stephan Müller 2020-01-09  155  		{
5b6f2811172c96 Stephan Müller 2020-01-09  156  			0x3b, 0xbe, 0x7a, 0xbd, 0x2b, 0x16, 0x02, 0x4c,
5b6f2811172c96 Stephan Müller 2020-01-09  157  			0xfc, 0xd3, 0x02, 0x15, 0xf0, 0x86, 0xd4, 0xdb,
5b6f2811172c96 Stephan Müller 2020-01-09  158  			0x49, 0xec, 0x26, 0x53, 0xd6, 0xc9, 0x6d, 0xad,
5b6f2811172c96 Stephan Müller 2020-01-09  159  			0x24, 0xca, 0x72, 0x89, 0x2c, 0xfa, 0x48, 0x18,
5b6f2811172c96 Stephan Müller 2020-01-09  160  			0xf7, 0x47, 0xb5, 0x2f, 0x92, 0xa2, 0x1b, 0xd9,
5b6f2811172c96 Stephan Müller 2020-01-09  161  			0x24, 0xa7, 0x2f, 0xa2, 0x0b,
5b6f2811172c96 Stephan Müller 2020-01-09  162  		}, {
5b6f2811172c96 Stephan Müller 2020-01-09  163  			0xd2, 0xaa, 0xf9, 0x76, 0x26, 0xc6, 0x13, 0xea,
5b6f2811172c96 Stephan Müller 2020-01-09  164  			0xb8, 0xde, 0xe6, 0x88, 0x8f, 0xc4, 0x7a, 0x7d,
5b6f2811172c96 Stephan Müller 2020-01-09  165  			0x9c, 0xb4, 0x1b, 0xd1, 0xd1, 0x8a, 0x40, 0xc9,
5b6f2811172c96 Stephan Müller 2020-01-09  166  			0xaa, 0x45, 0xa6, 0xb6, 0xb5, 0x6f, 0xf6, 0xbc,
5b6f2811172c96 Stephan Müller 2020-01-09  167  			0xbb, 0x77, 0x37, 0xbc, 0x5a, 0x2d, 0xcc, 0x84,
5b6f2811172c96 Stephan Müller 2020-01-09  168  			0x25, 0x68, 0x5e, 0xba, 0x16,
5b6f2811172c96 Stephan Müller 2020-01-09  169  		}, {
5b6f2811172c96 Stephan Müller 2020-01-09  170  			0x58, 0x66, 0x82, 0x88, 0x29, 0x19, 0xa4, 0xbb,
5b6f2811172c96 Stephan Müller 2020-01-09  171  			0x33, 0x42, 0xc9, 0x72, 0x0d, 0x68, 0x6e, 0xb9,
5b6f2811172c96 Stephan Müller 2020-01-09  172  			0xc6, 0xe0, 0x7a, 0xf9, 0x20, 0xca, 0x6d, 0x18,
5b6f2811172c96 Stephan Müller 2020-01-09  173  			0x35, 0xec, 0xfa, 0x9e, 0xf6, 0x3a, 0xa7, 0xb6,
5b6f2811172c96 Stephan Müller 2020-01-09  174  			0x92, 0x7a, 0xe5, 0xcd, 0xc5, 0x13, 0x9f, 0x65,
5b6f2811172c96 Stephan Müller 2020-01-09  175  			0x6a, 0xe1, 0xe4, 0x3f, 0xb9,
5b6f2811172c96 Stephan Müller 2020-01-09  176  		}, {
5b6f2811172c96 Stephan Müller 2020-01-09  177  			0xdd, 0xf1, 0x34, 0xca, 0x08, 0xe3, 0xce, 0x8a,
5b6f2811172c96 Stephan Müller 2020-01-09  178  			0x26, 0x6b, 0xce, 0x99, 0x8a, 0x84, 0xd2, 0x21,
5b6f2811172c96 Stephan Müller 2020-01-09  179  			0x98, 0x10, 0x95, 0x5f, 0x9f, 0xc3, 0xf2, 0xe4,
5b6f2811172c96 Stephan Müller 2020-01-09  180  			0x79, 0x75, 0xb5, 0x15, 0xa7, 0xa2, 0xf1, 0xc4,
5b6f2811172c96 Stephan Müller 2020-01-09  181  			0xdc, 0x67, 0xcb, 0x67, 0x8c, 0xb2, 0x1b, 0xd5,
5b6f2811172c96 Stephan Müller 2020-01-09  182  			0xd6, 0x8b, 0xc2, 0x34, 0xd6,
5b6f2811172c96 Stephan Müller 2020-01-09  183  		}, {
5b6f2811172c96 Stephan Müller 2020-01-09  184  			0xc3, 0x16, 0x9d, 0xf0, 0x78, 0x15, 0xab, 0xf2,
5b6f2811172c96 Stephan Müller 2020-01-09  185  			0x2f, 0xc9, 0x2e, 0xe1, 0xc6, 0x5e, 0xfa, 0x03,
5b6f2811172c96 Stephan Müller 2020-01-09  186  			0xaf, 0xd4, 0xd5, 0x47, 0x2a, 0xe8, 0x06, 0xe8,
5b6f2811172c96 Stephan Müller 2020-01-09  187  			0x7e, 0x0a, 0x71, 0xc7, 0x0d, 0x39, 0xb1, 0xa9,
5b6f2811172c96 Stephan Müller 2020-01-09  188  			0x5a, 0x49, 0xee, 0x8b, 0x2f, 0xcd, 0xea, 0x96,
5b6f2811172c96 Stephan Müller 2020-01-09  189  			0xcc, 0x08, 0x71, 0xef, 0x9c,
5b6f2811172c96 Stephan Müller 2020-01-09  190  		}, {
5b6f2811172c96 Stephan Müller 2020-01-09  191  			0x1a, 0x3d, 0x70, 0x39, 0xc2, 0x02, 0x4d, 0x3a,
5b6f2811172c96 Stephan Müller 2020-01-09  192  			0xaa, 0x14, 0x20, 0x88, 0x96, 0x4c, 0x7c, 0xe4,
5b6f2811172c96 Stephan Müller 2020-01-09  193  			0xaa, 0x49, 0x89, 0x30, 0x50, 0x96, 0xb6, 0xa7,
5b6f2811172c96 Stephan Müller 2020-01-09  194  			0x55, 0x0a, 0xf8, 0xd2, 0x4e, 0x83, 0x9d, 0x1f,
5b6f2811172c96 Stephan Müller 2020-01-09  195  			0x56, 0x49, 0x13, 0xc6, 0x46, 0x55, 0x73, 0x0d,
5b6f2811172c96 Stephan Müller 2020-01-09  196  			0x74, 0xcd, 0x81, 0xe0, 0x65,
5b6f2811172c96 Stephan Müller 2020-01-09  197  		}, {
5b6f2811172c96 Stephan Müller 2020-01-09  198  			0x4b, 0xf6, 0x49, 0x89, 0x2a, 0x9f, 0x67, 0xd7,
5b6f2811172c96 Stephan Müller 2020-01-09  199  			0xb8, 0x1d, 0xbb, 0x5d, 0xf0, 0x1b, 0x60, 0xb6,
5b6f2811172c96 Stephan Müller 2020-01-09  200  			0xb7, 0xf3, 0x86, 0x6d, 0xe0, 0x04, 0xa1, 0xbc,
5b6f2811172c96 Stephan Müller 2020-01-09  201  			0x3b, 0xb0, 0x10, 0x91, 0xe8, 0x22, 0x67, 0x5b,
5b6f2811172c96 Stephan Müller 2020-01-09  202  			0xe8, 0xf0, 0x4f, 0x82, 0x70, 0xc7, 0xe1, 0xc8,
5b6f2811172c96 Stephan Müller 2020-01-09  203  			0xd8, 0xad, 0x70, 0xcf, 0xf6,
5b6f2811172c96 Stephan Müller 2020-01-09  204  		}, {
5b6f2811172c96 Stephan Müller 2020-01-09  205  			0x60, 0x1f, 0x71, 0x07, 0x92, 0xae, 0xa0, 0x24,
5b6f2811172c96 Stephan Müller 2020-01-09  206  			0xb6, 0xa4, 0x10, 0x70, 0x1f, 0x94, 0x51, 0x9a,
5b6f2811172c96 Stephan Müller 2020-01-09  207  			0x5a, 0x81, 0xc4, 0x46, 0x78, 0x56, 0x71, 0xdd,
5b6f2811172c96 Stephan Müller 2020-01-09  208  			0x45, 0x63, 0x01, 0x34, 0x87, 0x79, 0xb4, 0xd5,
5b6f2811172c96 Stephan Müller 2020-01-09  209  			0x91, 0x79, 0xb9, 0x93, 0x11, 0x44, 0x50, 0xad,
5b6f2811172c96 Stephan Müller 2020-01-09  210  			0x64, 0x7e, 0x5c, 0xec, 0x16,
5b6f2811172c96 Stephan Müller 2020-01-09  211  		}, {
5b6f2811172c96 Stephan Müller 2020-01-09  212  			0x49, 0x2f, 0xa0, 0x45, 0xf8, 0xb0, 0x80, 0x88,
5b6f2811172c96 Stephan Müller 2020-01-09  213  			0x79, 0xeb, 0xb6, 0x82, 0x1c, 0xf3, 0x67, 0xc4,
5b6f2811172c96 Stephan Müller 2020-01-09  214  			0x88, 0x88, 0xe9, 0x75, 0x20, 0x54, 0x78, 0xc6,
5b6f2811172c96 Stephan Müller 2020-01-09  215  			0x5c, 0x59, 0xcf, 0xd9, 0x73, 0x12, 0x17, 0xf4,
5b6f2811172c96 Stephan Müller 2020-01-09  216  			0x30, 0x9c, 0xb7, 0x21, 0x45, 0xe2, 0xb6, 0x0c,
5b6f2811172c96 Stephan Müller 2020-01-09  217  			0x0c, 0xeb, 0x1b, 0xdc, 0xdc,
5b6f2811172c96 Stephan Müller 2020-01-09  218  		}
5b6f2811172c96 Stephan Müller 2020-01-09  219  	};
5b6f2811172c96 Stephan Müller 2020-01-09  220  	struct lrng_pool *lrng_pool, *lrng_pool_aligned;
5b6f2811172c96 Stephan Müller 2020-01-09  221  	u8 hash_df[sizeof(lrng_hash_df_selftest_result[0])]
5b6f2811172c96 Stephan Müller 2020-01-09  222  							__aligned(sizeof(u32));
5b6f2811172c96 Stephan Müller 2020-01-09  223  	u32 generated;
5b6f2811172c96 Stephan Müller 2020-01-09  224  	int ret = 0;
5b6f2811172c96 Stephan Müller 2020-01-09  225  
5b6f2811172c96 Stephan Müller 2020-01-09  226  	BUILD_BUG_ON(ARRAY_SIZE(lrng_hash_df_selftest_result) <
5b6f2811172c96 Stephan Müller 2020-01-09  227  							CONFIG_LRNG_POOL_SIZE);
5b6f2811172c96 Stephan Müller 2020-01-09  228  
5b6f2811172c96 Stephan Müller 2020-01-09 @229  	lrng_pool = kzalloc(sizeof(struct lrng_pool) + sizeof(LRNG_KCAPI_ALIGN),
                                                                                               ^^^^^^^^^^^^^^^^^^^^^^^^
Here too.


5b6f2811172c96 Stephan Müller 2020-01-09  230  			    GFP_KERNEL);
5b6f2811172c96 Stephan Müller 2020-01-09  231  	if (!lrng_pool)
5b6f2811172c96 Stephan Müller 2020-01-09  232  		return LRNG_SEFLTEST_ERROR_HASHDF;
5b6f2811172c96 Stephan Müller 2020-01-09  233  	lrng_pool_aligned = PTR_ALIGN(lrng_pool, sizeof(u32));
5b6f2811172c96 Stephan Müller 2020-01-09  234  
5b6f2811172c96 Stephan Müller 2020-01-09  235  	generated = __lrng_pool_hash_df(crypto_cb, NULL, lrng_pool_aligned,
5b6f2811172c96 Stephan Müller 2020-01-09  236  					hash_df, sizeof(hash_df) << 3);
5b6f2811172c96 Stephan Müller 2020-01-09  237  
5b6f2811172c96 Stephan Müller 2020-01-09  238  	if ((generated >> 3) != sizeof(hash_df) ||
5b6f2811172c96 Stephan Müller 2020-01-09  239  	    memcmp(hash_df, lrng_hash_df_selftest_result[CONFIG_LRNG_POOL_SIZE],
5b6f2811172c96 Stephan Müller 2020-01-09  240  		   sizeof(hash_df))) {
5b6f2811172c96 Stephan Müller 2020-01-09  241  		pr_err("LRNG Hash DF self-test FAILED\n");
5b6f2811172c96 Stephan Müller 2020-01-09  242  		ret = LRNG_SEFLTEST_ERROR_HASHDF;
5b6f2811172c96 Stephan Müller 2020-01-09  243  	}
5b6f2811172c96 Stephan Müller 2020-01-09  244  
5b6f2811172c96 Stephan Müller 2020-01-09  245  	kfree(lrng_pool);
5b6f2811172c96 Stephan Müller 2020-01-09  246  	return ret;
5b6f2811172c96 Stephan Müller 2020-01-09  247  }

---
0-DAY kernel test infrastructure                 Open Source Technology Center
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org Intel Corporation

^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v27 12/12] LRNG - add power-on and runtime self-tests
  2020-01-13 10:39         ` Dan Carpenter
@ 2020-01-13 10:46           ` Stephan Mueller
  0 siblings, 0 replies; 162+ messages in thread
From: Stephan Mueller @ 2020-01-13 10:46 UTC (permalink / raw)
  To: Dan Carpenter
  Cc: kbuild, kbuild-all, Arnd Bergmann, Greg Kroah-Hartman,
	linux-crypto, LKML, linux-api, Eric W. Biederman,
	Alexander E. Patrakov, Ahmed S. Darwish, Theodore Y. Ts'o,
	Willy Tarreau, Matthew Garrett, Vito Caputo, Andreas Dilger,
	Jan Kara, Ray Strode, William Jon McCann, zhangjs,
	Andy Lutomirski, Florian Weimer, Lennart Poettering,
	Nicolai Stange, Peter, Matthias, Marcelo Henrique Cerri,
	Roman Drahtmueller, Neil Horman, Randy Dunlap, Julia Lawall

Am Montag, 13. Januar 2020, 11:39:41 CET schrieb Dan Carpenter:

Hi Dan,

> Hi "Stephan,
> 
> url:   
> https://github.com/0day-ci/linux/commits/Stephan-M-ller/dev-random-a-new-ap
> proach-with-full-SP800-90B/20200110-084934 base:  
> https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git
> 68faa679b8be1a74e6663c21c3a9d25d32f1c079
> 
> If you fix the issue, kindly add following tag
> Reported-by: kbuild test robot <lkp@intel.com>
> Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
> 
> smatch warnings:
> drivers/char/lrng/lrng_selftest.c:117 lrng_pool_lfsr_selftest() warn:
> sizeof(NUMBER)? drivers/char/lrng/lrng_selftest.c:229
> lrng_hash_df_selftest() warn: sizeof(NUMBER)?
> 
> #
> https://github.com/0day-ci/linux/commit/5b6f2811172c968d8eb78167825c58557ea
> 91995 git remote add linux-review https://github.com/0day-ci/linux
> git remote update linux-review
> git checkout 5b6f2811172c968d8eb78167825c58557ea91995
> vim +117 drivers/char/lrng/lrng_selftest.c
> 
> 5b6f2811172c96 Stephan Müller 2020-01-09   89  static unsigned int
> lrng_pool_lfsr_selftest(void) 5b6f2811172c96 Stephan Müller 2020-01-09   90
>  {
> 5b6f2811172c96 Stephan Müller 2020-01-09   91  	/*
> 5b6f2811172c96 Stephan Müller 2020-01-09   92  	 * First, 67th and last
> entry of entropy pool. 5b6f2811172c96 Stephan Müller 2020-01-09   93  	 *
> 5b6f2811172c96 Stephan Müller 2020-01-09   94  	 * The 67th entry is picked
> because this one is the first to receive 5b6f2811172c96 Stephan Müller
> 2020-01-09   95  	 * an entry. As we start with 1 to inject into the 
LFSR,
> the 5b6f2811172c96 Stephan Müller 2020-01-09   96  	 * 67th entry should 
be
> equal to rol(1, 7) >> 3 considering that 5b6f2811172c96 Stephan Müller
> 2020-01-09   97  	 * all other values of the LFSR are zero and the the
> twist value of 0 5b6f2811172c96 Stephan Müller 2020-01-09   98  	 * is
> applied.
> 5b6f2811172c96 Stephan Müller 2020-01-09   99  	 */
> 5b6f2811172c96 Stephan Müller 2020-01-09  100  	static u32 const
> lrng_lfsr_selftest_result[][3] = { 5b6f2811172c96 Stephan Müller 2020-01-09
>  101  		{ 0xf56df24a, 0x00000010, 0x0e014939 }, 5b6f2811172c96 Stephan
> Müller 2020-01-09  102  		{ 0x4b130726, 0x00000010, 0x2802f509 
},
> 5b6f2811172c96 Stephan Müller 2020-01-09  103  		{ 0x87279152, 
0x00000010,
> 0x00150000 }, 5b6f2811172c96 Stephan Müller 2020-01-09  104  		{
> 0x0b67f997, 0x00000010, 0x00150000 }, 5b6f2811172c96 Stephan Müller
> 2020-01-09  105  		{ 0x4fea174f, 0x00000010, 0xcbf4a6ae }, 
5b6f2811172c96
> Stephan Müller 2020-01-09  106  		{ 0x77149108, 0x00000010, 
0x77bfadf2 },
> 5b6f2811172c96 Stephan Müller 2020-01-09  107  		{ 0x1e96037e, 
0x00000010,
> 0x18017e79 }, 5b6f2811172c96 Stephan Müller 2020-01-09  108  		{
> 0xc84acef2, 0x00000010, 0x6345f7a8 }, 5b6f2811172c96 Stephan Müller
> 2020-01-09  109  		{ 0x6a2eb6df, 0x00000010, 0x03950000 }, 
5b6f2811172c96
> Stephan Müller 2020-01-09  110  	};
> 5b6f2811172c96 Stephan Müller 2020-01-09  111  	struct lrng_pool *lrng_pool,
> *lrng_pool_aligned; 5b6f2811172c96 Stephan Müller 2020-01-09  112  	u32 
i,
> ret = LRNG_SELFTEST_PASSED; 5b6f2811172c96 Stephan Müller 2020-01-09  113
> 5b6f2811172c96 Stephan Müller 2020-01-09  114 
> 	BUILD_BUG_ON(ARRAY_SIZE(lrng_lfsr_selftest_result) < 5b6f2811172c96
> Stephan Müller 2020-01-09  115  						
	CONFIG_LRNG_POOL_SIZE);
> 5b6f2811172c96 Stephan Müller 2020-01-09  116
> 5b6f2811172c96 Stephan Müller 2020-01-09 @117  	lrng_pool =
> kzalloc(sizeof(struct lrng_pool) + sizeof(LRNG_KCAPI_ALIGN),
> ^^^^^^^^^^^^^^^^^^^^^^^^ Probably just LRNG_KCAPI_ALIGN is intended with no
> sizeof().


Yes, absolutely. Fixed in both cases.

Thank you!
> 
> 5b6f2811172c96 Stephan Müller 2020-01-09  118  			    
GFP_KERNEL);
> 5b6f2811172c96 Stephan Müller 2020-01-09  119  	if (!lrng_pool)
> 5b6f2811172c96 Stephan Müller 2020-01-09  120  		return
> LRNG_SEFLTEST_ERROR_LFSR; 5b6f2811172c96 Stephan Müller 2020-01-09  121 
> 	lrng_pool_aligned = PTR_ALIGN(lrng_pool, sizeof(u32)); 5b6f2811172c96
> Stephan Müller 2020-01-09  122
> 5b6f2811172c96 Stephan Müller 2020-01-09  123  	for (i = 1; i <=
> LRNG_POOL_SIZE; i++) 5b6f2811172c96 Stephan Müller 2020-01-09  124 
> 		_lrng_pool_lfsr_u32(lrng_pool_aligned, i); 5b6f2811172c96 
Stephan Müller
> 2020-01-09  125
> 5b6f2811172c96 Stephan Müller 2020-01-09  126  	if
> ((atomic_read_u32(&lrng_pool_aligned->pool[0]) != 5b6f2811172c96 Stephan
> Müller 2020-01-09  127  	    
> lrng_lfsr_selftest_result[CONFIG_LRNG_POOL_SIZE][0]) || 5b6f2811172c96
> Stephan Müller 2020-01-09  128  	   
> (atomic_read_u32(&lrng_pool_aligned->pool[67 & 5b6f2811172c96 Stephan
> Müller 2020-01-09  129  						      
(LRNG_POOL_SIZE - 1)]) !=
> 5b6f2811172c96 Stephan Müller 2020-01-09  130  	    
> lrng_lfsr_selftest_result[CONFIG_LRNG_POOL_SIZE][1]) || 5b6f2811172c96
> Stephan Müller 2020-01-09  131  	   
> (atomic_read_u32(&lrng_pool_aligned->pool[LRNG_POOL_SIZE - 1]) !=
> 5b6f2811172c96 Stephan Müller 2020-01-09  132  	    
> lrng_lfsr_selftest_result[CONFIG_LRNG_POOL_SIZE][2])) { 5b6f2811172c96
> Stephan Müller 2020-01-09  133  		pr_err("LRNG LFSR self-test 
FAILED\n");
> 5b6f2811172c96 Stephan Müller 2020-01-09  134  		ret =
> LRNG_SEFLTEST_ERROR_LFSR; 5b6f2811172c96 Stephan Müller 2020-01-09  135  	
}
> 5b6f2811172c96 Stephan Müller 2020-01-09  136
> 5b6f2811172c96 Stephan Müller 2020-01-09  137  	kfree(lrng_pool);
> 5b6f2811172c96 Stephan Müller 2020-01-09  138  	return ret;
> 5b6f2811172c96 Stephan Müller 2020-01-09  139  }
> 5b6f2811172c96 Stephan Müller 2020-01-09  140
> 5b6f2811172c96 Stephan Müller 2020-01-09  141  /*
> 5b6f2811172c96 Stephan Müller 2020-01-09  142   * The test vectors are
> generated with the hash_df_testvector_generation tool 5b6f2811172c96
> Stephan Müller 2020-01-09  143   * provided as part of the test tool set of
> the LRNG. 5b6f2811172c96 Stephan Müller 2020-01-09  144   */
> 5b6f2811172c96 Stephan Müller 2020-01-09  145  static unsigned int
> lrng_hash_df_selftest(void) 5b6f2811172c96 Stephan Müller 2020-01-09  146 
> {
> 5b6f2811172c96 Stephan Müller 2020-01-09  147  	const struct lrng_crypto_cb
> *crypto_cb = &lrng_cc20_crypto_cb; 5b6f2811172c96 Stephan Müller 2020-01-09
>  148
> 5b6f2811172c96 Stephan Müller 2020-01-09  149  	/*
> 5b6f2811172c96 Stephan Müller 2020-01-09  150  	 * The size of 45 bytes is
> chosen arbitrarily. Yet, this size should 5b6f2811172c96 Stephan Müller
> 2020-01-09  151  	 * ensure that we have at least two hash blocks plus 
some
> fraction 5b6f2811172c96 Stephan Müller 2020-01-09  152  	 * of a hash block
> generated. 5b6f2811172c96 Stephan Müller 2020-01-09  153  	 */
> 5b6f2811172c96 Stephan Müller 2020-01-09  154  	static u8 const
> lrng_hash_df_selftest_result[][45] = { 5b6f2811172c96 Stephan Müller
> 2020-01-09  155  		{
> 5b6f2811172c96 Stephan Müller 2020-01-09  156  			0x3b, 0xbe, 
0x7a, 0xbd,
> 0x2b, 0x16, 0x02, 0x4c, 5b6f2811172c96 Stephan Müller 2020-01-09  157 
> 			0xfc, 0xd3, 0x02, 0x15, 0xf0, 0x86, 0xd4, 0xdb, 
5b6f2811172c96 Stephan
> Müller 2020-01-09  158  			0x49, 0xec, 0x26, 0x53, 0xd6, 
0xc9, 0x6d, 0xad,
> 5b6f2811172c96 Stephan Müller 2020-01-09  159  			0x24, 0xca, 
0x72, 0x89,
> 0x2c, 0xfa, 0x48, 0x18, 5b6f2811172c96 Stephan Müller 2020-01-09  160 
> 			0xf7, 0x47, 0xb5, 0x2f, 0x92, 0xa2, 0x1b, 0xd9, 
5b6f2811172c96 Stephan
> Müller 2020-01-09  161  			0x24, 0xa7, 0x2f, 0xa2, 0x0b, 
5b6f2811172c96
> Stephan Müller 2020-01-09  162  		}, {
> 5b6f2811172c96 Stephan Müller 2020-01-09  163  			0xd2, 0xaa, 
0xf9, 0x76,
> 0x26, 0xc6, 0x13, 0xea, 5b6f2811172c96 Stephan Müller 2020-01-09  164 
> 			0xb8, 0xde, 0xe6, 0x88, 0x8f, 0xc4, 0x7a, 0x7d, 
5b6f2811172c96 Stephan
> Müller 2020-01-09  165  			0x9c, 0xb4, 0x1b, 0xd1, 0xd1, 
0x8a, 0x40, 0xc9,
> 5b6f2811172c96 Stephan Müller 2020-01-09  166  			0xaa, 0x45, 
0xa6, 0xb6,
> 0xb5, 0x6f, 0xf6, 0xbc, 5b6f2811172c96 Stephan Müller 2020-01-09  167 
> 			0xbb, 0x77, 0x37, 0xbc, 0x5a, 0x2d, 0xcc, 0x84, 
5b6f2811172c96 Stephan
> Müller 2020-01-09  168  			0x25, 0x68, 0x5e, 0xba, 0x16, 
5b6f2811172c96
> Stephan Müller 2020-01-09  169  		}, {
> 5b6f2811172c96 Stephan Müller 2020-01-09  170  			0x58, 0x66, 
0x82, 0x88,
> 0x29, 0x19, 0xa4, 0xbb, 5b6f2811172c96 Stephan Müller 2020-01-09  171 
> 			0x33, 0x42, 0xc9, 0x72, 0x0d, 0x68, 0x6e, 0xb9, 
5b6f2811172c96 Stephan
> Müller 2020-01-09  172  			0xc6, 0xe0, 0x7a, 0xf9, 0x20, 
0xca, 0x6d, 0x18,
> 5b6f2811172c96 Stephan Müller 2020-01-09  173  			0x35, 0xec, 
0xfa, 0x9e,
> 0xf6, 0x3a, 0xa7, 0xb6, 5b6f2811172c96 Stephan Müller 2020-01-09  174 
> 			0x92, 0x7a, 0xe5, 0xcd, 0xc5, 0x13, 0x9f, 0x65, 
5b6f2811172c96 Stephan
> Müller 2020-01-09  175  			0x6a, 0xe1, 0xe4, 0x3f, 0xb9, 
5b6f2811172c96
> Stephan Müller 2020-01-09  176  		}, {
> 5b6f2811172c96 Stephan Müller 2020-01-09  177  			0xdd, 0xf1, 
0x34, 0xca,
> 0x08, 0xe3, 0xce, 0x8a, 5b6f2811172c96 Stephan Müller 2020-01-09  178 
> 			0x26, 0x6b, 0xce, 0x99, 0x8a, 0x84, 0xd2, 0x21, 
5b6f2811172c96 Stephan
> Müller 2020-01-09  179  			0x98, 0x10, 0x95, 0x5f, 0x9f, 
0xc3, 0xf2, 0xe4,
> 5b6f2811172c96 Stephan Müller 2020-01-09  180  			0x79, 0x75, 
0xb5, 0x15,
> 0xa7, 0xa2, 0xf1, 0xc4, 5b6f2811172c96 Stephan Müller 2020-01-09  181 
> 			0xdc, 0x67, 0xcb, 0x67, 0x8c, 0xb2, 0x1b, 0xd5, 
5b6f2811172c96 Stephan
> Müller 2020-01-09  182  			0xd6, 0x8b, 0xc2, 0x34, 0xd6, 
5b6f2811172c96
> Stephan Müller 2020-01-09  183  		}, {
> 5b6f2811172c96 Stephan Müller 2020-01-09  184  			0xc3, 0x16, 
0x9d, 0xf0,
> 0x78, 0x15, 0xab, 0xf2, 5b6f2811172c96 Stephan Müller 2020-01-09  185 
> 			0x2f, 0xc9, 0x2e, 0xe1, 0xc6, 0x5e, 0xfa, 0x03, 
5b6f2811172c96 Stephan
> Müller 2020-01-09  186  			0xaf, 0xd4, 0xd5, 0x47, 0x2a, 
0xe8, 0x06, 0xe8,
> 5b6f2811172c96 Stephan Müller 2020-01-09  187  			0x7e, 0x0a, 
0x71, 0xc7,
> 0x0d, 0x39, 0xb1, 0xa9, 5b6f2811172c96 Stephan Müller 2020-01-09  188 
> 			0x5a, 0x49, 0xee, 0x8b, 0x2f, 0xcd, 0xea, 0x96, 
5b6f2811172c96 Stephan
> Müller 2020-01-09  189  			0xcc, 0x08, 0x71, 0xef, 0x9c, 
5b6f2811172c96
> Stephan Müller 2020-01-09  190  		}, {
> 5b6f2811172c96 Stephan Müller 2020-01-09  191  			0x1a, 0x3d, 
0x70, 0x39,
> 0xc2, 0x02, 0x4d, 0x3a, 5b6f2811172c96 Stephan Müller 2020-01-09  192 
> 			0xaa, 0x14, 0x20, 0x88, 0x96, 0x4c, 0x7c, 0xe4, 
5b6f2811172c96 Stephan
> Müller 2020-01-09  193  			0xaa, 0x49, 0x89, 0x30, 0x50, 
0x96, 0xb6, 0xa7,
> 5b6f2811172c96 Stephan Müller 2020-01-09  194  			0x55, 0x0a, 
0xf8, 0xd2,
> 0x4e, 0x83, 0x9d, 0x1f, 5b6f2811172c96 Stephan Müller 2020-01-09  195 
> 			0x56, 0x49, 0x13, 0xc6, 0x46, 0x55, 0x73, 0x0d, 
5b6f2811172c96 Stephan
> Müller 2020-01-09  196  			0x74, 0xcd, 0x81, 0xe0, 0x65, 
5b6f2811172c96
> Stephan Müller 2020-01-09  197  		}, {
> 5b6f2811172c96 Stephan Müller 2020-01-09  198  			0x4b, 0xf6, 
0x49, 0x89,
> 0x2a, 0x9f, 0x67, 0xd7, 5b6f2811172c96 Stephan Müller 2020-01-09  199 
> 			0xb8, 0x1d, 0xbb, 0x5d, 0xf0, 0x1b, 0x60, 0xb6, 
5b6f2811172c96 Stephan
> Müller 2020-01-09  200  			0xb7, 0xf3, 0x86, 0x6d, 0xe0, 
0x04, 0xa1, 0xbc,
> 5b6f2811172c96 Stephan Müller 2020-01-09  201  			0x3b, 0xb0, 
0x10, 0x91,
> 0xe8, 0x22, 0x67, 0x5b, 5b6f2811172c96 Stephan Müller 2020-01-09  202 
> 			0xe8, 0xf0, 0x4f, 0x82, 0x70, 0xc7, 0xe1, 0xc8, 
5b6f2811172c96 Stephan
> Müller 2020-01-09  203  			0xd8, 0xad, 0x70, 0xcf, 0xf6, 
5b6f2811172c96
> Stephan Müller 2020-01-09  204  		}, {
> 5b6f2811172c96 Stephan Müller 2020-01-09  205  			0x60, 0x1f, 
0x71, 0x07,
> 0x92, 0xae, 0xa0, 0x24, 5b6f2811172c96 Stephan Müller 2020-01-09  206 
> 			0xb6, 0xa4, 0x10, 0x70, 0x1f, 0x94, 0x51, 0x9a, 
5b6f2811172c96 Stephan
> Müller 2020-01-09  207  			0x5a, 0x81, 0xc4, 0x46, 0x78, 
0x56, 0x71, 0xdd,
> 5b6f2811172c96 Stephan Müller 2020-01-09  208  			0x45, 0x63, 
0x01, 0x34,
> 0x87, 0x79, 0xb4, 0xd5, 5b6f2811172c96 Stephan Müller 2020-01-09  209 
> 			0x91, 0x79, 0xb9, 0x93, 0x11, 0x44, 0x50, 0xad, 
5b6f2811172c96 Stephan
> Müller 2020-01-09  210  			0x64, 0x7e, 0x5c, 0xec, 0x16, 
5b6f2811172c96
> Stephan Müller 2020-01-09  211  		}, {
> 5b6f2811172c96 Stephan Müller 2020-01-09  212  			0x49, 0x2f, 
0xa0, 0x45,
> 0xf8, 0xb0, 0x80, 0x88, 5b6f2811172c96 Stephan Müller 2020-01-09  213 
> 			0x79, 0xeb, 0xb6, 0x82, 0x1c, 0xf3, 0x67, 0xc4, 
5b6f2811172c96 Stephan
> Müller 2020-01-09  214  			0x88, 0x88, 0xe9, 0x75, 0x20, 
0x54, 0x78, 0xc6,
> 5b6f2811172c96 Stephan Müller 2020-01-09  215  			0x5c, 0x59, 
0xcf, 0xd9,
> 0x73, 0x12, 0x17, 0xf4, 5b6f2811172c96 Stephan Müller 2020-01-09  216 
> 			0x30, 0x9c, 0xb7, 0x21, 0x45, 0xe2, 0xb6, 0x0c, 
5b6f2811172c96 Stephan
> Müller 2020-01-09  217  			0x0c, 0xeb, 0x1b, 0xdc, 0xdc, 
5b6f2811172c96
> Stephan Müller 2020-01-09  218  		}
> 5b6f2811172c96 Stephan Müller 2020-01-09  219  	};
> 5b6f2811172c96 Stephan Müller 2020-01-09  220  	struct lrng_pool *lrng_pool,
> *lrng_pool_aligned; 5b6f2811172c96 Stephan Müller 2020-01-09  221  	u8
> hash_df[sizeof(lrng_hash_df_selftest_result[0])] 5b6f2811172c96 Stephan
> Müller 2020-01-09  222  							
__aligned(sizeof(u32)); 5b6f2811172c96
> Stephan Müller 2020-01-09  223  	u32 generated;
> 5b6f2811172c96 Stephan Müller 2020-01-09  224  	int ret = 0;
> 5b6f2811172c96 Stephan Müller 2020-01-09  225
> 5b6f2811172c96 Stephan Müller 2020-01-09  226 
> 	BUILD_BUG_ON(ARRAY_SIZE(lrng_hash_df_selftest_result) < 5b6f2811172c96
> Stephan Müller 2020-01-09  227  						
	CONFIG_LRNG_POOL_SIZE);
> 5b6f2811172c96 Stephan Müller 2020-01-09  228
> 5b6f2811172c96 Stephan Müller 2020-01-09 @229  	lrng_pool =
> kzalloc(sizeof(struct lrng_pool) + sizeof(LRNG_KCAPI_ALIGN),
> ^^^^^^^^^^^^^^^^^^^^^^^^ Here too.
> 
> 
> 5b6f2811172c96 Stephan Müller 2020-01-09  230  			    
GFP_KERNEL);
> 5b6f2811172c96 Stephan Müller 2020-01-09  231  	if (!lrng_pool)
> 5b6f2811172c96 Stephan Müller 2020-01-09  232  		return
> LRNG_SEFLTEST_ERROR_HASHDF; 5b6f2811172c96 Stephan Müller 2020-01-09  233 
> 	lrng_pool_aligned = PTR_ALIGN(lrng_pool, sizeof(u32)); 5b6f2811172c96
> Stephan Müller 2020-01-09  234
> 5b6f2811172c96 Stephan Müller 2020-01-09  235  	generated =
> __lrng_pool_hash_df(crypto_cb, NULL, lrng_pool_aligned, 5b6f2811172c96
> Stephan Müller 2020-01-09  236  					
hash_df, sizeof(hash_df) << 3);
> 5b6f2811172c96 Stephan Müller 2020-01-09  237
> 5b6f2811172c96 Stephan Müller 2020-01-09  238  	if ((generated >> 3) !=
> sizeof(hash_df) || 5b6f2811172c96 Stephan Müller 2020-01-09  239  	   
> memcmp(hash_df, lrng_hash_df_selftest_result[CONFIG_LRNG_POOL_SIZE],
> 5b6f2811172c96 Stephan Müller 2020-01-09  240  		   sizeof(hash_df))) 
{
> 5b6f2811172c96 Stephan Müller 2020-01-09  241  		pr_err("LRNG Hash DF
> self-test FAILED\n"); 5b6f2811172c96 Stephan Müller 2020-01-09  242  		
ret
> = LRNG_SEFLTEST_ERROR_HASHDF; 5b6f2811172c96 Stephan Müller 2020-01-09  243
>  	}
> 5b6f2811172c96 Stephan Müller 2020-01-09  244
> 5b6f2811172c96 Stephan Müller 2020-01-09  245  	kfree(lrng_pool);
> 5b6f2811172c96 Stephan Müller 2020-01-09  246  	return ret;
> 5b6f2811172c96 Stephan Müller 2020-01-09  247  }
> 
> ---
> 0-DAY kernel test infrastructure                 Open Source Technology
> Center https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org Intel
> Corporation



Ciao
Stephan



^ permalink raw reply	[flat|nested] 162+ messages in thread

* [PATCH v28 00/12] /dev/random - a new approach with full SP800-90B
  2020-01-09  8:29     ` [PATCH v27 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                         ` (11 preceding siblings ...)
  2020-01-09  8:35       ` [PATCH v27 12/12] LRNG - add power-on and runtime self-tests Stephan Müller
@ 2020-01-15 10:31       ` Stephan Müller
  2020-01-15 10:31         ` [PATCH v28 01/12] Linux Random Number Generator Stephan Müller
                           ` (12 more replies)
  12 siblings, 13 replies; 162+ messages in thread
From: Stephan Müller @ 2020-01-15 10:31 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap, Julia Lawall, Dan Carpenter

Hi,

The following patch set provides a different approach to /dev/random which is
called Linux Random Number Generator (LRNG) to collect entropy within the Linux
kernel. The main improvements compared to the existing /dev/random is to provide
sufficient entropy during boot time as well as in virtual environments and when
using SSDs. A secondary design goal is to limit the impact of the entropy
collection on massive parallel systems and also allow the use accelerated
cryptographic primitives. Also, all steps of the entropic data processing are
testable.

The LRNG patch set allows a user to select use of the existing /dev/random or
the LRNG during compile time. As the LRNG provides API and ABI compatible
interfaces to the existing /dev/random implementation, the user can freely chose
the RNG implementation without affecting kernel or user space operations.

This patch set provides early boot-time entropy which implies that no
additional flags to the getrandom(2) system call discussed recently on
the LKML is considered to be necessary. Yet, if additional flags are
introduced to cover special hardware, the LRNG implementation will also
provide them to be fully ABI and API compliant as already discussed on
LKML.

The LRNG is fully compliant to SP800-90B requirements and is shipped with a
full SP800-90B assessment and all required test tools. The existing /dev/random
implementation on the other hand has architectural limitations which
does not easily allow to bring the implementation in compliance with
SP800-90B. The key statement that causes concern is SP800-90B section
3.1.6. This section denies crediting entropy to multiple similar noise
sources. This section explicitly references different noise sources resting
on the timing of events and their derivatives (i.e. it is a direct complaint
to the existing existing /dev/random implementation). Therefore, SP800-90B
now denies the very issue mentioned in [1] with the existing /dev/random
implementation for a long time: crediting entropy to interrupts as well as
crediting entropy to derivatives of interrupts (HID and disk events). This is
not permissible with SP800-90B.

SP800-90B specifies various requirements for the noise source(s) that seed any
DRNG including SP800-90A DRBGs. In about a year from now, SP800-90B will be
mandated for all noise sources that provide entropy to DRBGs as part of a FIPS
140-[2|3] validation or other evaluation types. That means, if we there are no
solutions to comply with the requirements of SP800-90B found till one year
from now, any random number generation and ciphers based on random numbers
on Linux will be considered and treated as not applicable and delivering
no entropy! As /dev/urandom, getrandom(2) and /dev/random are the most
common and prevalent noise sources for DRNGs, all these DRNGs are affected.
This applies across the board for all validations of cryptography executing on
Linux (kernel and user space modules).

For users that are not interested in SP800-90B, the entire code for the
compliance as well as test interfaces can be deselected at compile time.

The design and implementation is driven by a set of goals described in [1]
that the LRNG completely implements. Furthermore, [1] includes the full
assessment of the SP800-90B compliance as well as a comparison with RNG
design suggestions of SP800-90C, and AIS20/31.

The LRNG provides a complete separation of the noise source maintenance
and the collection of entropy into an entropy pool from the post-processing
using a pseudo-random number generator. Different DRNGs are supported,
including:

* The LRNG can be compile-time enabled to replace the existing /dev/random
  implementation. When not selecting the LRNG at compile time (default), the
  existing /dev/random implementation is built.

* Built-in ChaCha20 DRNG which has no dependency to other kernel
  frameworks.

* SP800-90A DRBG using the kernel crypto API including its accelerated
  raw cipher implementations. This implies that the output of /dev/random,
  getrandom(2), /dev/urandom or get_random_bytes is fully compliant to
  SP800-90A.

* Arbitrary DRNGs registered with the kernel crypto API

* Full compliance with SP800-90B which covers the startup and runtime health
  tests mandated by SP800-90B as well as providing the test tools and test
  interfaces to obtain raw noise data securely. The test tools are provided at
  [1].

Booting the patch with the kernel command line option
"dyndbg=file drivers/char/lrng/* +p" generates logs indicating the operation
of the LRNG. Each log is pre-pended with "lrng".

The LRNG has a flexible design by allowing an easy replacement of the
deterministic random number generator component.

Compared to the existing /dev/random implementation, the compiled binary
is smaller when the LRNG is compiled with all options equal to the
existing /dev/random (i.e. only CONFIG_LRNG is set): random.o is 52.5 kBytes
whereas all LRNG object files are in 49 kBytes in size. The fully
SP800-90A/SP800-90B compliant binary code (CONFIG_LRNG,
CONFIG_LRNG_DRNG_SWITCH, CONFIG_LRNG_DRBG, CONFIG_LRNG_HEALTH_TESTS)
uses some 61 kBytes. In addition, the LRNG is about 50% faster in the
performance critical interrupt handler code path compared to the existing
/dev/random implementation.

[1] http://www.chronox.de/lrng.html - If the patch is accepted, I would
be volunteering to convert the documentation into RST format and
contribute it to the Linux kernel documentation directory.

Changes (compared to the previous patch set):

* make comments compliant to kernel-doc style

* update LRNG_RCT_CUTOFF from 30 to 31 (a cutoff of 30 implies
  an alpha of 2^-29 and a cutoff of 31 is an alpha of 2^-30 - both
  values are in line with SP800-90B, but to be consistent with documentation
  update the cutoff value) - reported by Marcos Portnoi

* remove lrng_drng_generate_helper_full that was only needed by removed
  TRNG support

* Remove "unlikely" from lrng_drng_lock which seems to cause additional grief
  with sparse. Note, sparse will still report a lock context imbalance as it
  used to since we indeed have two lock contexts as documented in
  lrng_drng_switch. Reported-by: kbuild test robot <lkp@intel.com>

* Fix allocation size calculation in self-test code as reported by
  Dan Carpenter <dan.carpenter@oracle.com>

This patch requires the presence of patch
75551dbf112c992bc6c99a972990b3f272247e23 from Ted Tso's kernel tree
(specifically the addition of GRND_INSECURE to random.h)

As a side node: With the switchable DRNG support offered in this patch set,
the following areas could be removed. As the existing /dev/random has no support
for switchable DRNGs, however, this is not yet feasible though.

* remove lrng_ready_list and all code around it in lrng_interfaces.c

* remove the kernel crypto API RNG API to avoid having two random number
  providing APIs - this would imply that all RNGs developed for this API would
  be converted to the LRNG interface

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>

Stephan Mueller (12):
  Linux Random Number Generator
  LRNG - allocate one DRNG instance per NUMA node
  LRNG - sysctls and /proc interface
  LRNG - add switchable DRNG support
  crypto: DRBG - externalize DRBG functions for LRNG
  LRNG - add SP800-90A DRBG extension
  LRNG - add kernel crypto API PRNG extension
  crypto: provide access to a static Jitter RNG state
  LRNG - add Jitter RNG fast noise source
  LRNG - add SP800-90B compliant health tests
  LRNG - add interface for gathering of raw entropy
  LRNG - add power-on and runtime self-tests

 MAINTAINERS                                   |   7 +
 crypto/drbg.c                                 |  16 +-
 crypto/jitterentropy-kcapi.c                  |   3 +-
 crypto/jitterentropy.c                        |  25 +-
 drivers/char/Kconfig                          |   2 +
 drivers/char/Makefile                         |   9 +-
 drivers/char/lrng/Kconfig                     | 203 ++++++
 drivers/char/lrng/Makefile                    |  19 +
 drivers/char/lrng/lrng_archrandom.c           |  94 +++
 drivers/char/lrng/lrng_aux.c                  | 148 ++++
 drivers/char/lrng/lrng_chacha20.c             | 265 ++++++++
 drivers/char/lrng/lrng_chacha20.h             |  25 +
 drivers/char/lrng/lrng_drbg.c                 | 260 +++++++
 drivers/char/lrng/lrng_drng.c                 | 400 +++++++++++
 drivers/char/lrng/lrng_health.c               | 409 +++++++++++
 drivers/char/lrng/lrng_interfaces.c           | 637 ++++++++++++++++++
 drivers/char/lrng/lrng_internal.h             | 305 +++++++++
 drivers/char/lrng/lrng_jent.c                 |  89 +++
 drivers/char/lrng/lrng_kcapi.c                | 327 +++++++++
 drivers/char/lrng/lrng_lfsr.h                 | 152 +++++
 drivers/char/lrng/lrng_numa.c                 | 101 +++
 drivers/char/lrng/lrng_pool.c                 | 588 ++++++++++++++++
 drivers/char/lrng/lrng_proc.c                 | 163 +++++
 drivers/char/lrng/lrng_selftest.c             | 418 ++++++++++++
 drivers/char/lrng/lrng_sw_noise.c             | 102 +++
 drivers/char/lrng/lrng_sw_noise.h             |  57 ++
 drivers/char/lrng/lrng_switch.c               | 183 +++++
 drivers/char/lrng/lrng_testing.c              | 271 ++++++++
 include/crypto/drbg.h                         |   7 +
 .../crypto/internal}/jitterentropy.h          |   3 +
 include/linux/lrng.h                          |  63 ++
 31 files changed, 5341 insertions(+), 10 deletions(-)
 create mode 100644 drivers/char/lrng/Kconfig
 create mode 100644 drivers/char/lrng/Makefile
 create mode 100644 drivers/char/lrng/lrng_archrandom.c
 create mode 100644 drivers/char/lrng/lrng_aux.c
 create mode 100644 drivers/char/lrng/lrng_chacha20.c
 create mode 100644 drivers/char/lrng/lrng_chacha20.h
 create mode 100644 drivers/char/lrng/lrng_drbg.c
 create mode 100644 drivers/char/lrng/lrng_drng.c
 create mode 100644 drivers/char/lrng/lrng_health.c
 create mode 100644 drivers/char/lrng/lrng_interfaces.c
 create mode 100644 drivers/char/lrng/lrng_internal.h
 create mode 100644 drivers/char/lrng/lrng_jent.c
 create mode 100644 drivers/char/lrng/lrng_kcapi.c
 create mode 100644 drivers/char/lrng/lrng_lfsr.h
 create mode 100644 drivers/char/lrng/lrng_numa.c
 create mode 100644 drivers/char/lrng/lrng_pool.c
 create mode 100644 drivers/char/lrng/lrng_proc.c
 create mode 100644 drivers/char/lrng/lrng_selftest.c
 create mode 100644 drivers/char/lrng/lrng_sw_noise.c
 create mode 100644 drivers/char/lrng/lrng_sw_noise.h
 create mode 100644 drivers/char/lrng/lrng_switch.c
 create mode 100644 drivers/char/lrng/lrng_testing.c
 rename {crypto => include/crypto/internal}/jitterentropy.h (84%)
 create mode 100644 include/linux/lrng.h

-- 
2.24.1





^ permalink raw reply	[flat|nested] 162+ messages in thread

* [PATCH v28 01/12] Linux Random Number Generator
  2020-01-15 10:31       ` [PATCH v28 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
@ 2020-01-15 10:31         ` Stephan Müller
  2020-01-16  0:11           ` Randy Dunlap
  2020-01-15 10:32         ` [PATCH v28 02/12] LRNG - allocate one DRNG instance per NUMA node Stephan Müller
                           ` (11 subsequent siblings)
  12 siblings, 1 reply; 162+ messages in thread
From: Stephan Müller @ 2020-01-15 10:31 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap, Julia Lawall, Dan Carpenter

In an effort to provide a flexible implementation for a random number
generator that also delivers entropy during early boot time, allows
replacement of the deterministic random number generation mechanism,
implement the various components in separate code for easier
maintenance, and provide compliance to SP800-90[A|B|C], introduce
the Linux Random Number Generator (LRNG) framework.

The general design is as follows. Additional implementation details
are given in [1]. The LRNG consists of the following components:

1. The LRNG implements a DRNG. The DRNG always generates the
requested amount of output. When using the SP800-90A terminology
it operates without prediction resistance. The secondary DRNG
maintains a counter of how many bytes were generated since last
re-seed and a timer of the elapsed time since last re-seed. If either
the counter or the timer reaches a threshold, the secondary DRNG is
seeded from the entropy pool.

In case the Linux kernel detects a NUMA system, one secondary DRNG
instance per NUMA node is maintained.

2. The DRNG is seeded by concatenating the data from the
following sources:

(a) the output of the entropy pool,

(b) the Jitter RNG if available and enabled, and

(c) the CPU-based noise source such as Intel RDRAND if available and
enabled.

The entropy estimate of the data of all noise sources are added to
form the entropy estimate of the data used to seed the DRNG with.
The LRNG ensures, however, that the DRNG after seeding is at
maximum the security strength of the DRNG.

The LRNG is designed such that none of these noise sources can dominate
the other noise sources to provide seed data to the DRNG during due to
the following:

(a) During boot time, the amount of received interrupts are the trigger
points to (re)seed the DRNG.

(b) At runtime, the available entropy from the slow noise source is
concatenated with a pre-defined amount of data from the fast noise
sources. In addition, each DRNG reseed operation triggers external
noise source providers to deliver one block of data.

3. The entropy pool accumulates entropy obtained from certain events,
which will henceforth be collectively called "slow noise sources".
The entropy pool collects noise data from slow noise sources. Any data
received by the LRNG from the slow noise sources is inserted into the
entropy pool using an LFSR with a primitive and irreducible polynomial.
The following sources of entropy are used:

 (a) When an interrupt occurs, the high-resolution time stamp is mixed
into the LFSR. This time stamp is credited with heuristically implied
entropy.

 (b) HID event data like the key stroke or the mouse coordinates are
mixed into the LFSR. This data is not credited with entropy by the LRNG.

 (c) Device drivers may provide data that is mixed into the LFSR. This
data is not credited with entropy by the LRNG.

 (d) After the entropy pool is ``read'' by the DRNG, the data
used to seed the DRNG is mixed back into the entropy pool to
stir the pool. This data is not credited with entropy by the LRNG.

Any data provided from user space by either writing to /dev/random,
/dev/urandom or the IOCTL of RNDADDENTROPY on both device files
are always injected into the entropy pool.

In addition, when a hardware random number generator covered by the
Linux kernel HW generator framework wants to deliver random numbers,
it is injected into the entropy pool as well. HW generator noise source
is handled separately from the other noise source due to the fact that
the HW generator framework may decide by itself when to deliver data
whereas the other noise sources always requested for data driven by the
LRNG operation. Similarly any user space provided data is inserted into
the entropy pool.

When the DRNG requires data from the entropy pool, the entire
entropy pool is processed with an SP800-90A section 10.3.1 compliant
hash_df function to generate random numbers.

To speed up the interrupt handling code of the LRNG, the time stamp
collected for an interrupt event is truncated to the 8 least
significant bits. 64 truncated time stamps are concatenated and then
jointly inserted into the LFSR. During boot time, until the fully seeded
stage is reached, each time stamp with its 32 least significant bits is
inserted into the LFSR at the time of arrival.

The LRNG allows the DRNG mechanism to be changed at runtime. Per default,
a ChaCha20-based DRNG is used. The ChaCha20-DRNG implemented for the
LRNG is also provided as a stand-alone user space deterministic random
number generator. The LRNG also offers an SP800-90A DRBG based on the
Linux kernel crypto API DRBG implementation.

The processing of entropic data from the noise source before injecting
them into the DRNG is performed with the following mathematical
operations:

1. LFSR: The 8 least significant bits of the time stamp data received
from the interrupts are processed with an LFSR. That LFSR is implemented
identically to the LSFR used in the existing /dev/random implementation
except that it is capable of processing an entire word and that a
different polynomial is used. The reason for the different polynomial
is performance in a performance sensitive code section, the interrupt
handler. The chosen polynomials have 4 taps. Also, this LFSR-approach
is used in the OpenBSD /dev/random equivalent.

2. Concatenation: The temporary seed buffer used to seed the DRNG is
a concatenation of parts of the entropy pool data, and the CPU noise
source output.

The DRNG always tries to seed itself with 256 bits of entropy, except
during boot. In any case, if the noise sources cannot deliver that
amount, the available entropy is used and the DRNG keeps track on how
much entropy it was seeded with. The entropy implied by the LRNG
available in the entropy pool may be too conservative. To ensure
that during boot time all available entropy from the entropy pool is
transferred to the DRNG, the hash_df function always generates 256
data bits during boot to seed the DRNG. During boot, the DRNG is
seeded as follows:

1. The DRNG is reseeded from the entropy pool and potentially the fast
noise sources if the entropy pool has collected at least 32 bits of
entropy from the interrupt noise source. The goal of this step is to
ensure that the DRNG receives some initial entropy as early as
possible. In addition it receives the entropy available from
the fast noise sources.

2. The DRNG is reseeded from the entropy pool and potentially the fast
noise sources if all noise sources collectively can provide at least
128 bits of entropy.

3. The DRNG is reseeded from the entropy pool and potentially the fast
noise sources if all noise sources collectivel can provide at least 256
bits.

At the time of the reseeding steps, the DRNG requests as much entropy as
is available in order to skip certain steps and reach the seeding level
of 256 bits. This may imply that one or more of the aforementioned steps
are skipped.

In all listed steps, the DRNG is (re)seeded with a number of random
bytes from the entropy pool that is at most the amount of entropy
present in the entropy pool. This means that when the entropy pool
contains 128 or 256 bits of entropy, the DRNG is seeded with that
amount of entropy as well.

Before the DRNG is seeded with 256 bits of entropy in step 3,
requests of random data from /dev/random are not processed.

The hash_df operation providing random data from the entropy pool will
always require that all entropy sources collectively can deliver at
least 129 entropy bits as configured with (128 bits of entropy for
seeding plus one bit of entropy that is lost with the post
processing as defined in SP800-90B).

The DRNG operates as deterministic random number generator with the
following properties:

* The maximum number of random bytes that can be generated with one
DRNG generate operation is limited to 4096 bytes. When longer random
numbers are requested, multiple DRNG generate operations are performed.
The ChaCha20 DRNG as well as the SP800-90A DRBGs implement an update of
their state after completing a generate request for backtracking
resistance.

* The secondary DRNG is reseeded with whatever entropy is available –
in the worst case where no additional entropy can be provided by the
noise sources, the DRNG is not re-seeded and continues its operation
to try to reseed again after again the expiry of one of these thresholds:

 - If the last reseeding of the secondary DRNG is more than 600 seconds
   ago, or

 - 2^20 DRNG generate operations are performed, whatever comes first, or

 - the secondary DRNG is forced to reseed before the next generation of
   random numbers if data has been injected into the LRNG by writing data
   into /dev/random or /dev/urandom.

The chosen values prevent high-volume requests from user space to cause
frequent reseeding operations which drag down the performance of the
DRNG.

With the automatic reseeding after 600 seconds, the LRNG is triggered
to reseed itself before the first request after a suspend that put the
hardware to sleep for longer than 600 seconds.

The LRNG uses the following runtime memory using the currently
smallest configuration:

* 576 bytes (512 bytes for the entropy pool and 64 for the entropy pool
  meta data) for the entropy pool management

* 64 bytes per CPU for the time stamp array

To support smaller devices including IoT environments, this patch
allows reducing the runtime memory footprint of the LRNG at compile
time by selecting smaller entropy pool sizes.

The entropy pool has support for sizes of 256, 128 and 64 bytes supported
by primitive and irreducible polynomials.

The time stamp array is reduced to one atomic_t variable per CPU, i.e.
4 bytes when CONFIG_BASE_SMALL is selected during kernel
configuration. This implies that after the receipt of 4 interrupts on
one CPU, the data is injected into the LFSR. Depending on the behavior
of the CPU caches, this may imply that the average interrupt handler
execution time increases a bit, since instead of injecting 8 atomic_t
values at one given time into the LFSR, only one is processed which
may incur cache misses.

When selecting the compilation of a kernel for a small environment,
prevent the allocation of a buffer up to 4096 bytes to serve user space
requests. In this case, the stack variable of 64 bytes is used to serve
all user space requests.

The LRNG has the following properties:

* internal noise source: interrupts timing with fast boot time seeding

* 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().

* lockless LFSR to collect raw entropy supporing concurrency-free
  use of massive parallel systems

* use of standalone ChaCha20 based RNG with the option to use a
  different DRNG selectable at compile time

* "atomic" seeding of secondary DRBG to ensure full entropy transport

* instantiate one DRNG per NUMA node

* support for runtime switchable output DRNGs

* use of only well-defined entropy-preserving operations to collect,
compress and forward entropy: concatenation, LFSR, SP800-90A hash_df
function

* compile-time selectable entropy pool size: the choice also
uses the applicable LFSR polynomial to maintain the entropy pool
size

* support of small systems by allowing the reduction of the
runtime memory needs

Further details including the rationale for the design choices and
properties of the LRNG together with testing is provided at [1].
In addition, the documentation explains the conducted regression
tests to verify that the LRNG is API and ABI compatible with the
existing /dev/random implementation.

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

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Mathematical aspects Reviewed-by: "Peter, Matthias" <matthias.peter@bsi.bund.de>
Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 MAINTAINERS                         |   7 +
 drivers/char/Kconfig                |   2 +
 drivers/char/Makefile               |   9 +-
 drivers/char/lrng/Kconfig           |  67 +++
 drivers/char/lrng/Makefile          |   9 +
 drivers/char/lrng/lrng_archrandom.c |  94 ++++
 drivers/char/lrng/lrng_aux.c        | 148 +++++++
 drivers/char/lrng/lrng_chacha20.c   | 265 ++++++++++++
 drivers/char/lrng/lrng_chacha20.h   |  25 ++
 drivers/char/lrng/lrng_drng.c       | 400 +++++++++++++++++
 drivers/char/lrng/lrng_interfaces.c | 638 ++++++++++++++++++++++++++++
 drivers/char/lrng/lrng_internal.h   | 296 +++++++++++++
 drivers/char/lrng/lrng_lfsr.h       | 152 +++++++
 drivers/char/lrng/lrng_pool.c       | 588 +++++++++++++++++++++++++
 drivers/char/lrng/lrng_sw_noise.c   | 102 +++++
 drivers/char/lrng/lrng_sw_noise.h   |  57 +++
 include/linux/lrng.h                |  63 +++
 17 files changed, 2921 insertions(+), 1 deletion(-)
 create mode 100644 drivers/char/lrng/Kconfig
 create mode 100644 drivers/char/lrng/Makefile
 create mode 100644 drivers/char/lrng/lrng_archrandom.c
 create mode 100644 drivers/char/lrng/lrng_aux.c
 create mode 100644 drivers/char/lrng/lrng_chacha20.c
 create mode 100644 drivers/char/lrng/lrng_chacha20.h
 create mode 100644 drivers/char/lrng/lrng_drng.c
 create mode 100644 drivers/char/lrng/lrng_interfaces.c
 create mode 100644 drivers/char/lrng/lrng_internal.h
 create mode 100644 drivers/char/lrng/lrng_lfsr.h
 create mode 100644 drivers/char/lrng/lrng_pool.c
 create mode 100644 drivers/char/lrng/lrng_sw_noise.c
 create mode 100644 drivers/char/lrng/lrng_sw_noise.h
 create mode 100644 include/linux/lrng.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 8982c6e013b3..f9beac15783c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9606,6 +9606,13 @@ F:	Documentation/core-api/atomic_ops.rst
 F:	Documentation/core-api/refcount-vs-atomic.rst
 F:	Documentation/memory-barriers.txt
 
+LINUX RANDOM NUMBER GENERATOR (LRNG) DRIVER
+M:	Stephan Mueller <smueller@chronox.de>
+S:	Maintained
+W:	https://www.chronox.de/lrng.html
+F:	drivers/char/lrng/*
+F:	include/linux/lrng.h
+
 LIS3LV02D ACCELEROMETER DRIVER
 M:	Eric Piel <eric.piel@tremplin-utc.net>
 S:	Maintained
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 26956c006987..1e758735f633 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -535,6 +535,8 @@ config ADI
 	  and SSM (Silicon Secured Memory).  Intended consumers of this
 	  driver include crash and makedumpfile.
 
+source "drivers/char/lrng/Kconfig"
+
 endmenu
 
 config RANDOM_TRUST_CPU
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 7c5ea6f9df14..46ede09fd6d3 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -3,7 +3,14 @@
 # Makefile for the kernel character device drivers.
 #
 
-obj-y				+= mem.o random.o
+obj-y				+= mem.o
+
+ifeq ($(CONFIG_LRNG),y)
+  obj-y				+= lrng/
+else
+  obj-y				+= random.o
+endif
+
 obj-$(CONFIG_TTY_PRINTK)	+= ttyprintk.o
 obj-y				+= misc.o
 obj-$(CONFIG_ATARI_DSP56K)	+= dsp56k.o
diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
new file mode 100644
index 000000000000..56f13efd3592
--- /dev/null
+++ b/drivers/char/lrng/Kconfig
@@ -0,0 +1,67 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Linux Random Number Generator configuration
+#
+
+menuconfig LRNG
+	bool "Linux Random Number Generator"
+	help
+	  The Linux Random Number Generator (LRNG) is the replacement
+	  of the existing /dev/random provided with drivers/char/random.c.
+	  It generates entropy from different noise sources and
+	  delivers significant entropy during boot.
+
+if LRNG
+
+choice
+	prompt "LRNG Entropy Pool Size"
+	default LRNG_POOL_SIZE_4096
+	help
+	  Select the size of the LRNG entropy pool. The size of the
+	  entropy pool is relevant for the amount of entropy that
+	  the LRNG can maintain as a maximum. The larger the size
+	  of the entropy pool is the more entropy can be maintained
+	  but the less often older entropic values are overwritten
+	  with new entropy.
+
+	config LRNG_POOL_SIZE_512
+		bool "512 bits"
+
+	config LRNG_POOL_SIZE_1024
+		bool "1024 bits"
+
+	config LRNG_POOL_SIZE_2048
+		bool "2048 bits"
+
+	config LRNG_POOL_SIZE_4096
+		bool "4096 bits (default)"
+
+	config LRNG_POOL_SIZE_8192
+		bool "8192 bits"
+
+	config LRNG_POOL_SIZE_16384
+		bool "16384 bits"
+
+	config LRNG_POOL_SIZE_32768
+		bool "32768 bits"
+
+	config LRNG_POOL_SIZE_65536
+		bool "65536 bits"
+
+	config LRNG_POOL_SIZE_131072
+		bool "131072 bits"
+endchoice
+
+config LRNG_POOL_SIZE
+	int
+	default 0 if LRNG_POOL_SIZE_512
+	default 1 if LRNG_POOL_SIZE_1024
+	default 2 if LRNG_POOL_SIZE_2048
+	default 3 if LRNG_POOL_SIZE_4096
+	default 4 if LRNG_POOL_SIZE_8192
+	default 5 if LRNG_POOL_SIZE_16384
+	default 6 if LRNG_POOL_SIZE_32768
+	default 7 if LRNG_POOL_SIZE_65536
+	default 8 if LRNG_POOL_SIZE_131072
+
+endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
new file mode 100644
index 000000000000..1d2a0211973d
--- /dev/null
+++ b/drivers/char/lrng/Makefile
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for the Linux Random Number Generator.
+#
+
+obj-y				+= lrng_pool.o lrng_aux.o \
+				   lrng_sw_noise.o lrng_archrandom.o \
+				   lrng_drng.o lrng_chacha20.o \
+				   lrng_interfaces.o \
diff --git a/drivers/char/lrng/lrng_archrandom.c b/drivers/char/lrng/lrng_archrandom.c
new file mode 100644
index 000000000000..eeba708d025f
--- /dev/null
+++ b/drivers/char/lrng/lrng_archrandom.c
@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG Fast Noise Source: CPU-based noise source
+ *
+ * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/random.h>
+
+#include "lrng_internal.h"
+
+/*
+ * Estimated entropy of data is a 32th of LRNG_DRNG_SECURITY_STRENGTH_BITS.
+ * As we have no ability to review the implementation of those noise sources,
+ * it is prudent to have a conservative estimate here.
+ */
+#define LRNG_ARCHRANDOM_DEFAULT_STRENGTH (LRNG_DRNG_SECURITY_STRENGTH_BITS>>5)
+#define LRNG_ARCHRANDOM_TRUST_CPU_STRENGTH LRNG_DRNG_SECURITY_STRENGTH_BITS
+#ifdef CONFIG_RANDOM_TRUST_CPU
+static u32 archrandom = LRNG_ARCHRANDOM_TRUST_CPU_STRENGTH;
+#else
+static u32 archrandom = LRNG_ARCHRANDOM_DEFAULT_STRENGTH;
+#endif
+module_param(archrandom, uint, 0644);
+MODULE_PARM_DESC(archrandom, "Entropy in bits of 256 data bits from CPU noise "
+			     "source (e.g. RDRAND)");
+
+static int __init lrng_parse_trust_cpu(char *arg)
+{
+	int ret;
+	bool trust_cpu = false;
+
+	ret = kstrtobool(arg, &trust_cpu);
+	if (ret)
+		return ret;
+
+	if (trust_cpu)
+		archrandom = LRNG_ARCHRANDOM_TRUST_CPU_STRENGTH;
+	else
+		archrandom = LRNG_ARCHRANDOM_DEFAULT_STRENGTH;
+
+	return 0;
+}
+early_param("random.trust_cpu", lrng_parse_trust_cpu);
+
+/**
+ * lrng_get_arch() - Get CPU noise source entropy
+ *
+ * @outbuf: buffer to store entropy of size LRNG_DRNG_SECURITY_STRENGTH_BYTES
+ *
+ * Return:
+ * * > 0 on success where value provides the added entropy in bits
+ * *   0 if no fast source was available
+ */
+u32 lrng_get_arch(u8 *outbuf)
+{
+	u32 i, ent_bits = archrandom;
+
+	/* operate on full blocks */
+	BUILD_BUG_ON(LRNG_DRNG_SECURITY_STRENGTH_BYTES % sizeof(unsigned long));
+	/* ensure we have aligned buffers */
+	BUILD_BUG_ON(LRNG_KCAPI_ALIGN % sizeof(unsigned long));
+
+	if (!ent_bits)
+		return 0;
+
+	for (i = 0; i < LRNG_DRNG_SECURITY_STRENGTH_BYTES;
+	     i += sizeof(unsigned long)) {
+		if (!arch_get_random_seed_long((unsigned long *)(outbuf + i)) &&
+		    !arch_get_random_long((unsigned long *)(outbuf + i))) {
+			archrandom = 0;
+			return 0;
+		}
+	}
+
+	/* Obtain entropy statement -- cap entropy to buffer size in bits */
+	ent_bits = min_t(u32, ent_bits, LRNG_DRNG_SECURITY_STRENGTH_BITS);
+	pr_debug("obtained %u bits of entropy from CPU RNG noise source\n",
+		 ent_bits);
+	return ent_bits;
+}
+
+u32 lrng_slow_noise_req_entropy(u32 required_entropy_bits)
+{
+	u32 arch_ent_bits = min_t(u32, archrandom,
+				  LRNG_DRNG_SECURITY_STRENGTH_BITS);
+	u32 fast_noise_entropy = arch_ent_bits + lrng_jent_entropylevel();
+
+	if (fast_noise_entropy > required_entropy_bits)
+		return 0;
+	return (required_entropy_bits - fast_noise_entropy);
+}
diff --git a/drivers/char/lrng/lrng_aux.c b/drivers/char/lrng/lrng_aux.c
new file mode 100644
index 000000000000..b66c7795d067
--- /dev/null
+++ b/drivers/char/lrng/lrng_aux.c
@@ -0,0 +1,148 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG auxiliary interfaces
+ *
+ * Copyright (C) 2019 Stephan Mueller <smueller@chronox.de>
+ * Copyright (C) 2017 Jason A. Donenfeld <Jason@zx2c4.com>. All
+ * Rights Reserved.
+ * Copyright (C) 2016 Jason Cooper <jason@lakedaemon.net>
+ */
+
+#include <linux/mm.h>
+#include <linux/random.h>
+
+#include "lrng_internal.h"
+
+struct batched_entropy {
+	union {
+		u64 entropy_u64[LRNG_DRNG_BLOCKSIZE / sizeof(u64)];
+		u32 entropy_u32[LRNG_DRNG_BLOCKSIZE / sizeof(u32)];
+	};
+	unsigned int position;
+	spinlock_t batch_lock;
+};
+
+/*
+ * Get a random word for internal kernel use only. The quality of the random
+ * number is either as good as RDRAND or as good as /dev/urandom, with the
+ * goal of being quite fast and not depleting entropy.
+ */
+static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_u64) = {
+	.batch_lock	= __SPIN_LOCK_UNLOCKED(batched_entropy_u64.lock),
+};
+
+u64 get_random_u64(void)
+{
+	u64 ret;
+	unsigned long flags;
+	struct batched_entropy *batch;
+
+#if BITS_PER_LONG == 64
+	if (arch_get_random_long((unsigned long *)&ret))
+		return ret;
+#else
+	if (arch_get_random_long((unsigned long *)&ret) &&
+	    arch_get_random_long((unsigned long *)&ret + 1))
+		return ret;
+#endif
+
+	lrng_debug_report_seedlevel("get_random_u64");
+
+	batch = raw_cpu_ptr(&batched_entropy_u64);
+	spin_lock_irqsave(&batch->batch_lock, flags);
+	if (batch->position % ARRAY_SIZE(batch->entropy_u64) == 0) {
+		lrng_drng_get_atomic((u8 *)batch->entropy_u64,
+				      LRNG_DRNG_BLOCKSIZE);
+		batch->position = 0;
+	}
+	ret = batch->entropy_u64[batch->position++];
+	spin_unlock_irqrestore(&batch->batch_lock, flags);
+	return ret;
+}
+EXPORT_SYMBOL(get_random_u64);
+
+static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_u32) = {
+	.batch_lock	= __SPIN_LOCK_UNLOCKED(batched_entropy_u32.lock),
+};
+
+u32 get_random_u32(void)
+{
+	u32 ret;
+	unsigned long flags;
+	struct batched_entropy *batch;
+
+	if (arch_get_random_int(&ret))
+		return ret;
+
+	lrng_debug_report_seedlevel("get_random_u32");
+
+	batch = raw_cpu_ptr(&batched_entropy_u32);
+	spin_lock_irqsave(&batch->batch_lock, flags);
+	if (batch->position % ARRAY_SIZE(batch->entropy_u32) == 0) {
+		lrng_drng_get_atomic((u8 *)batch->entropy_u32,
+				      LRNG_DRNG_BLOCKSIZE);
+		batch->position = 0;
+	}
+	ret = batch->entropy_u32[batch->position++];
+	spin_unlock_irqrestore(&batch->batch_lock, flags);
+	return ret;
+}
+EXPORT_SYMBOL(get_random_u32);
+
+/*
+ * It's important to invalidate all potential batched entropy that might
+ * be stored before the crng is initialized, which we can do lazily by
+ * simply resetting the counter to zero so that it's re-extracted on the
+ * next usage.
+ */
+void invalidate_batched_entropy(void)
+{
+	int cpu;
+	unsigned long flags;
+
+	for_each_possible_cpu(cpu) {
+		struct batched_entropy *batched_entropy;
+
+		batched_entropy = per_cpu_ptr(&batched_entropy_u32, cpu);
+		spin_lock_irqsave(&batched_entropy->batch_lock, flags);
+		batched_entropy->position = 0;
+		spin_unlock(&batched_entropy->batch_lock);
+
+		batched_entropy = per_cpu_ptr(&batched_entropy_u64, cpu);
+		spin_lock(&batched_entropy->batch_lock);
+		batched_entropy->position = 0;
+		spin_unlock_irqrestore(&batched_entropy->batch_lock, flags);
+	}
+}
+
+/**
+ * randomize_page - Generate a random, page aligned address
+ * @start:	The smallest acceptable address the caller will take.
+ * @range:	The size of the area, starting at @start, within which the
+ *		random address must fall.
+ *
+ * If @start + @range would overflow, @range is capped.
+ *
+ * NOTE: Historical use of randomize_range, which this replaces, presumed that
+ * @start was already page aligned.  We now align it regardless.
+ *
+ * Return: A page aligned address within [start, start + range).  On error,
+ * @start is returned.
+ */
+unsigned long randomize_page(unsigned long start, unsigned long range)
+{
+	if (!PAGE_ALIGNED(start)) {
+		range -= PAGE_ALIGN(start) - start;
+		start = PAGE_ALIGN(start);
+	}
+
+	if (start > ULONG_MAX - range)
+		range = ULONG_MAX - start;
+
+	range >>= PAGE_SHIFT;
+
+	if (range == 0)
+		return start;
+
+	return start + (get_random_long() % range << PAGE_SHIFT);
+}
diff --git a/drivers/char/lrng/lrng_chacha20.c b/drivers/char/lrng/lrng_chacha20.c
new file mode 100644
index 000000000000..6d149ff355c6
--- /dev/null
+++ b/drivers/char/lrng/lrng_chacha20.c
@@ -0,0 +1,265 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * Backend for the LRNG providing the cryptographic primitives using
+ * ChaCha20 cipher implementations.
+ *
+ * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <crypto/chacha.h>
+#include <linux/cryptohash.h>
+#include <linux/lrng.h>
+#include <linux/random.h>
+#include <linux/slab.h>
+
+#include "lrng_chacha20.h"
+#include "lrng_internal.h"
+
+/******************************* ChaCha20 DRNG *******************************/
+
+#define CHACHA_BLOCK_WORDS	(CHACHA_BLOCK_SIZE / sizeof(u32))
+
+struct chacha20_state {
+	struct chacha20_block block;
+};
+
+/*
+ * Have a static memory blocks for the ChaCha20 DRNG instance to avoid calling
+ * kmalloc too early in the boot cycle. For subsequent allocation requests,
+ * such as per-NUMA-node DRNG instances, kmalloc will be used.
+ */
+struct chacha20_state chacha20;
+
+/**
+ * Update of the ChaCha20 state by either using an unused buffer part or by
+ * generating one ChaCha20 block which is half of the state of the ChaCha20.
+ * The block is XORed into the key part of the state. This shall ensure
+ * backtracking resistance as well as a proper mix of the ChaCha20 state once
+ * the key is injected.
+ */
+static void lrng_chacha20_update(struct chacha20_state *chacha20_state,
+				 u32 *buf, u32 used_words)
+{
+	struct chacha20_block *chacha20 = &chacha20_state->block;
+	u32 i, tmp[CHACHA_BLOCK_WORDS];
+
+	BUILD_BUG_ON(sizeof(struct chacha20_block) != CHACHA_BLOCK_SIZE);
+	BUILD_BUG_ON(CHACHA_BLOCK_SIZE != 2 * CHACHA_KEY_SIZE);
+
+	if (used_words > CHACHA_KEY_SIZE_WORDS) {
+		chacha20_block(&chacha20->constants[0], (u8 *)tmp);
+		for (i = 0; i < CHACHA_KEY_SIZE_WORDS; i++)
+			chacha20->key.u[i] ^= tmp[i];
+		memzero_explicit(tmp, sizeof(tmp));
+	} else {
+		for (i = 0; i < CHACHA_KEY_SIZE_WORDS; i++)
+			chacha20->key.u[i] ^= buf[i + used_words];
+	}
+
+	/* Deterministic increment of nonce as required in RFC 7539 chapter 4 */
+	chacha20->nonce[0]++;
+	if (chacha20->nonce[0] == 0)
+		chacha20->nonce[1]++;
+	if (chacha20->nonce[1] == 0)
+		chacha20->nonce[2]++;
+
+	/* Leave counter untouched as it is start value is undefined in RFC */
+}
+
+/*
+ * Seed the ChaCha20 DRNG by injecting the input data into the key part of
+ * the ChaCha20 state. If the input data is longer than the ChaCha20 key size,
+ * perform a ChaCha20 operation after processing of key size input data.
+ * This operation shall spread out the entropy into the ChaCha20 state before
+ * new entropy is injected into the key part.
+ */
+static int lrng_cc20_drng_seed_helper(void *drng, const u8 *inbuf, u32 inbuflen)
+{
+	struct chacha20_state *chacha20_state = (struct chacha20_state *)drng;
+	struct chacha20_block *chacha20 = &chacha20_state->block;
+
+	while (inbuflen) {
+		u32 i, todo = min_t(u32, inbuflen, CHACHA_KEY_SIZE);
+
+		for (i = 0; i < todo; i++)
+			chacha20->key.b[i] ^= inbuf[i];
+
+		/* Break potential dependencies between the inbuf key blocks */
+		lrng_chacha20_update(chacha20_state, NULL,
+				     CHACHA_BLOCK_WORDS);
+		inbuf += todo;
+		inbuflen -= todo;
+	}
+
+	return 0;
+}
+
+/*
+ * Chacha20 DRNG generation of random numbers: the stream output of ChaCha20
+ * is the random number. After the completion of the generation of the
+ * stream, the entire ChaCha20 state is updated.
+ *
+ * Note, as the ChaCha20 implements a 32 bit counter, we must ensure
+ * that this function is only invoked for at most 2^32 - 1 ChaCha20 blocks
+ * before a reseed or an update happens. This is ensured by the variable
+ * outbuflen which is a 32 bit integer defining the number of bytes to be
+ * generated by the ChaCha20 DRNG. At the end of this function, an update
+ * operation is invoked which implies that the 32 bit counter will never be
+ * overflown in this implementation.
+ */
+static int lrng_cc20_drng_generate_helper(void *drng, u8 *outbuf, u32 outbuflen)
+{
+	struct chacha20_state *chacha20_state = (struct chacha20_state *)drng;
+	struct chacha20_block *chacha20 = &chacha20_state->block;
+	u32 aligned_buf[CHACHA_BLOCK_WORDS], ret = outbuflen,
+	    used = CHACHA_BLOCK_WORDS;
+	int zeroize_buf = 0;
+
+	while (outbuflen >= CHACHA_BLOCK_SIZE) {
+		chacha20_block(&chacha20->constants[0], outbuf);
+		outbuf += CHACHA_BLOCK_SIZE;
+		outbuflen -= CHACHA_BLOCK_SIZE;
+	}
+
+	if (outbuflen) {
+		chacha20_block(&chacha20->constants[0], (u8 *)aligned_buf);
+		memcpy(outbuf, aligned_buf, outbuflen);
+		used = ((outbuflen + sizeof(aligned_buf[0]) - 1) /
+			sizeof(aligned_buf[0]));
+		zeroize_buf = 1;
+	}
+
+	lrng_chacha20_update(chacha20_state, aligned_buf, used);
+
+	if (zeroize_buf)
+		memzero_explicit(aligned_buf, sizeof(aligned_buf));
+
+	return ret;
+}
+
+void lrng_cc20_init_state(struct chacha20_state *state)
+{
+	struct chacha20_block *chacha20 = &state->block;
+	unsigned long v;
+	u32 i;
+
+	lrng_cc20_init_rfc7539(chacha20);
+
+	for (i = 0; i < CHACHA_KEY_SIZE_WORDS; i++) {
+		chacha20->key.u[i] ^= jiffies;
+		chacha20->key.u[i] ^= random_get_entropy();
+		if (arch_get_random_seed_long(&v) || arch_get_random_long(&v))
+			chacha20->key.u[i] ^= v;
+	}
+
+	for (i = 0; i < 3; i++) {
+		chacha20->nonce[i] ^= jiffies;
+		chacha20->nonce[i] ^= random_get_entropy();
+		if (arch_get_random_seed_long(&v) || arch_get_random_long(&v))
+			chacha20->nonce[i] ^= v;
+	}
+
+	pr_info("ChaCha20 core initialized\n");
+}
+
+/*
+ * Allocation of the DRNG state
+ */
+static void *lrng_cc20_drng_alloc(u32 sec_strength)
+{
+	struct chacha20_state *state = NULL;
+
+	if (sec_strength > CHACHA_KEY_SIZE) {
+		pr_err("Security strength of ChaCha20 DRNG (%u bits) lower "
+		       "than requested by LRNG (%u bits)\n",
+			CHACHA_KEY_SIZE * 8, sec_strength * 8);
+		return ERR_PTR(-EINVAL);
+	}
+	if (sec_strength < CHACHA_KEY_SIZE)
+		pr_warn("Security strength of ChaCha20 DRNG (%u bits) higher "
+			"than requested by LRNG (%u bits)\n",
+			CHACHA_KEY_SIZE * 8, sec_strength * 8);
+
+	state = kmalloc(sizeof(struct chacha20_state), GFP_KERNEL);
+	if (!state)
+		return ERR_PTR(-ENOMEM);
+	pr_debug("memory for ChaCha20 core allocated\n");
+
+	lrng_cc20_init_state(state);
+
+	return state;
+}
+
+static void lrng_cc20_drng_dealloc(void *drng)
+{
+	struct chacha20_state *chacha20_state = (struct chacha20_state *)drng;
+
+	if (drng == &chacha20) {
+		memzero_explicit(chacha20_state, sizeof(*chacha20_state));
+		pr_debug("static ChaCha20 core zeroized\n");
+		return;
+	}
+
+	pr_debug("ChaCha20 core zeroized and freed\n");
+	kzfree(chacha20_state);
+}
+
+/******************************* Hash Operation *******************************/
+
+static void *lrng_cc20_hash_alloc(const u8 *key, u32 keylen)
+{
+	pr_info("Hash SHA-1 allocated\n");
+	return NULL;
+}
+
+static void lrng_cc20_hash_dealloc(void *hash)
+{
+}
+
+static u32 lrng_cc20_hash_digestsize(void *hash)
+{
+	return (SHA_DIGEST_WORDS * sizeof(u32));
+}
+
+static int lrng_cc20_hash_buffer(void *hash, const u8 *inbuf, u32 inbuflen,
+				 u8 *digest)
+{
+	u32 i;
+	u32 workspace[SHA_WORKSPACE_WORDS];
+
+	WARN_ON(inbuflen % (SHA_WORKSPACE_WORDS * sizeof(u32)));
+
+	sha_init((u32 *)digest);
+	for (i = 0; i < inbuflen; i += (SHA_WORKSPACE_WORDS * sizeof(u32)))
+		sha_transform((u32 *)digest, (inbuf + i), workspace);
+	memzero_explicit(workspace, sizeof(workspace));
+
+	return 0;
+}
+
+static const char *lrng_cc20_drng_name(void)
+{
+	const char *cc20_drng_name = "ChaCha20 DRNG";
+	return cc20_drng_name;
+}
+
+static const char *lrng_cc20_hash_name(void)
+{
+	const char *cc20_hash_name = "SHA-1";
+	return cc20_hash_name;
+}
+
+const struct lrng_crypto_cb lrng_cc20_crypto_cb = {
+	.lrng_drng_name			= lrng_cc20_drng_name,
+	.lrng_hash_name			= lrng_cc20_hash_name,
+	.lrng_drng_alloc		= lrng_cc20_drng_alloc,
+	.lrng_drng_dealloc		= lrng_cc20_drng_dealloc,
+	.lrng_drng_seed_helper		= lrng_cc20_drng_seed_helper,
+	.lrng_drng_generate_helper	= lrng_cc20_drng_generate_helper,
+	.lrng_hash_alloc		= lrng_cc20_hash_alloc,
+	.lrng_hash_dealloc		= lrng_cc20_hash_dealloc,
+	.lrng_hash_digestsize		= lrng_cc20_hash_digestsize,
+	.lrng_hash_buffer		= lrng_cc20_hash_buffer,
+};
diff --git a/drivers/char/lrng/lrng_chacha20.h b/drivers/char/lrng/lrng_chacha20.h
new file mode 100644
index 000000000000..0387ad59cfbc
--- /dev/null
+++ b/drivers/char/lrng/lrng_chacha20.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
+/*
+ * LRNG ChaCha20 definitions
+ *
+ * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#include <crypto/chacha.h>
+
+/* State according to RFC 7539 section 2.3 */
+struct chacha20_block {
+	u32 constants[4];
+	union {
+#define CHACHA_KEY_SIZE_WORDS (CHACHA_KEY_SIZE / sizeof(u32))
+		u32 u[CHACHA_KEY_SIZE_WORDS];
+		u8  b[CHACHA_KEY_SIZE];
+	} key;
+	u32 counter;
+	u32 nonce[3];
+};
+
+static inline void lrng_cc20_init_rfc7539(struct chacha20_block *chacha20)
+{
+	memcpy(&chacha20->constants[0], "expand 32-byte k", 16);
+}
diff --git a/drivers/char/lrng/lrng_drng.c b/drivers/char/lrng/lrng_drng.c
new file mode 100644
index 000000000000..3f7fde556d66
--- /dev/null
+++ b/drivers/char/lrng/lrng_drng.c
@@ -0,0 +1,400 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG DRNG processing
+ *
+ * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/lrng.h>
+
+#include "lrng_internal.h"
+
+/*
+ * Maximum number of seconds between DRNG reseed intervals of the DRNG. Note,
+ * this is enforced with the next request of random numbers from the
+ * DRNG. Setting this value to zero implies a reseeding attempt before every
+ * generated random number.
+ */
+int lrng_drng_reseed_max_time = 600;
+
+static atomic_t lrng_avail = ATOMIC_INIT(0);
+
+DEFINE_MUTEX(lrng_crypto_cb_update);
+
+/* DRNG for /dev/urandom, getrandom(2), get_random_bytes */
+static struct lrng_drng lrng_drng_init = {
+	.drng		= &chacha20,
+	.crypto_cb	= &lrng_cc20_crypto_cb,
+	.lock		= __MUTEX_INITIALIZER(lrng_drng_init.lock),
+	.spin_lock	= __SPIN_LOCK_UNLOCKED(lrng_drng_init.spin_lock)
+};
+
+/*
+ * DRNG for get_random_bytes when called in atomic context. This
+ * DRNG will always use the ChaCha20 DRNG. It will never benefit from a
+ * DRNG switch like the "regular" DRNG. If there was no DRNG switch, the atomic
+ * DRNG is identical to the "regular" DRNG.
+ *
+ * The reason for having this is due to the fact that DRNGs other than
+ * the ChaCha20 DRNG may sleep.
+ */
+static struct lrng_drng lrng_drng_atomic = {
+	.drng		= &chacha20,
+	.crypto_cb	= &lrng_cc20_crypto_cb,
+	.spin_lock	= __SPIN_LOCK_UNLOCKED(lrng_drng_atomic.spin_lock)
+};
+
+/********************************** Helper ************************************/
+
+bool lrng_get_available(void)
+{
+	return likely(atomic_read(&lrng_avail));
+}
+
+void lrng_set_available(void)
+{
+	atomic_set(&lrng_avail, 1);
+}
+
+struct lrng_drng *lrng_drng_init_instance(void)
+{
+	return &lrng_drng_init;
+}
+
+struct lrng_drng *lrng_drng_atomic_instance(void)
+{
+	return &lrng_drng_atomic;
+}
+
+void lrng_drng_reset(struct lrng_drng *drng)
+{
+	atomic_set(&drng->requests, LRNG_DRNG_RESEED_THRESH);
+	drng->last_seeded = jiffies;
+	drng->fully_seeded = false;
+	drng->force_reseed = true;
+	pr_debug("reset DRNG\n");
+}
+
+/************************* Random Number Generation ***************************/
+
+/* Inject a data buffer into the DRNG */
+static void lrng_drng_inject(struct lrng_drng *drng,
+			     const u8 *inbuf, u32 inbuflen)
+{
+	const char *drng_type = unlikely(drng == &lrng_drng_atomic) ?
+				"atomic" : "regular";
+	unsigned long flags = 0;
+
+	BUILD_BUG_ON(LRNG_DRNG_RESEED_THRESH > INT_MAX);
+	pr_debug("seeding %s DRNG with %u bytes\n", drng_type, inbuflen);
+	lrng_drng_lock(drng, &flags);
+	if (drng->crypto_cb->lrng_drng_seed_helper(drng->drng,
+						    inbuf, inbuflen) < 0) {
+		pr_warn("seeding of %s DRNG failed\n", drng_type);
+		atomic_set(&drng->requests, 1);
+	} else {
+		pr_debug("%s DRNG stats since last seeding: %lu secs; "
+			 "generate calls: %d\n", drng_type,
+			 (time_after(jiffies, drng->last_seeded) ?
+			  (jiffies - drng->last_seeded) : 0) / HZ,
+			 (LRNG_DRNG_RESEED_THRESH -
+			  atomic_read(&drng->requests)));
+		drng->last_seeded = jiffies;
+		atomic_set(&drng->requests, LRNG_DRNG_RESEED_THRESH);
+		drng->force_reseed = false;
+
+		if (drng->drng == lrng_drng_atomic.drng) {
+			lrng_drng_atomic.last_seeded = jiffies;
+			atomic_set(&lrng_drng_atomic.requests,
+				   LRNG_DRNG_RESEED_THRESH);
+			lrng_drng_atomic.force_reseed = false;
+		}
+	}
+	lrng_drng_unlock(drng, &flags);
+}
+
+/*
+ * Perform the seeding of the DRNG with data from noise source
+ */
+static inline int _lrng_drng_seed(struct lrng_drng *drng)
+{
+	struct entropy_buf seedbuf __aligned(LRNG_KCAPI_ALIGN);
+	unsigned long flags = 0;
+	u32 total_entropy_bits;
+	int ret;
+
+	lrng_drng_lock(drng, &flags);
+	total_entropy_bits = lrng_fill_seed_buffer(drng->crypto_cb, drng->hash,
+						   &seedbuf, 0);
+	lrng_drng_unlock(drng, &flags);
+
+	/* Allow the seeding operation to be called again */
+	lrng_pool_unlock();
+	lrng_init_ops(total_entropy_bits);
+	ret = total_entropy_bits >> 3;
+
+	lrng_drng_inject(drng, (u8 *)&seedbuf, sizeof(seedbuf));
+	memzero_explicit(&seedbuf, sizeof(seedbuf));
+
+	return ret;
+}
+
+static int lrng_drng_get(struct lrng_drng *drng, u8 *outbuf, u32 outbuflen);
+static void lrng_drng_seed(struct lrng_drng *drng)
+{
+	int ret = _lrng_drng_seed(drng);
+
+	if (ret >= LRNG_DRNG_SECURITY_STRENGTH_BYTES)
+		drng->fully_seeded = true;
+
+	BUILD_BUG_ON(LRNG_MIN_SEED_ENTROPY_BITS >
+		     LRNG_DRNG_SECURITY_STRENGTH_BITS);
+
+	/*
+	 * Reseed atomic DRNG from current DRNG,
+	 *
+	 * We can obtain random numbers from DRNG as the lock type
+	 * chosen by lrng_drng_get is usable with the current caller.
+	 */
+	if ((drng->drng != lrng_drng_atomic.drng) &&
+	    (lrng_drng_atomic.force_reseed ||
+	     atomic_read(&lrng_drng_atomic.requests) <= 0 ||
+	     time_after(jiffies, lrng_drng_atomic.last_seeded +
+			lrng_drng_reseed_max_time * HZ))) {
+		u8 seedbuf[LRNG_DRNG_SECURITY_STRENGTH_BYTES]
+						__aligned(LRNG_KCAPI_ALIGN);
+
+		ret = lrng_drng_get(drng, seedbuf, sizeof(seedbuf));
+
+		if (ret < 0) {
+			pr_warn("Error generating random numbers for atomic "
+				"DRNG: %d\n", ret);
+		} else {
+			lrng_drng_inject(&lrng_drng_atomic, seedbuf, ret);
+		}
+		memzero_explicit(&seedbuf, sizeof(seedbuf));
+	}
+}
+
+static inline void _lrng_drng_seed_work(struct lrng_drng *drng, u32 node)
+{
+	pr_debug("reseed triggered by interrupt noise source for DRNG on NUMA "
+		 "node %d\n", node);
+	lrng_drng_seed(drng);
+	if (drng->fully_seeded) {
+		/* Prevent reseed storm */
+		drng->last_seeded += node * 100 * HZ;
+		/* Prevent draining of pool on idle systems */
+		lrng_drng_reseed_max_time += 100;
+	}
+}
+
+/*
+ * DRNG reseed trigger: Kernel thread handler triggered by the schedule_work()
+ */
+void lrng_drng_seed_work(struct work_struct *dummy)
+{
+	struct lrng_drng **lrng_drng = lrng_drng_instances();
+	u32 node;
+
+	if (lrng_drng) {
+		for_each_online_node(node) {
+			struct lrng_drng *drng = lrng_drng[node];
+
+			if (drng && !drng->fully_seeded) {
+				_lrng_drng_seed_work(drng, node);
+				goto out;
+			}
+		}
+		lrng_pool_all_numa_nodes_seeded();
+	} else {
+		if (!lrng_drng_init.fully_seeded)
+			_lrng_drng_seed_work(&lrng_drng_init, 0);
+	}
+
+out:
+	/* Allow the seeding operation to be called again */
+	lrng_pool_unlock();
+}
+
+/* Force all DRNGs to reseed before next generation */
+void lrng_drng_force_reseed(void)
+{
+	struct lrng_drng **lrng_drng = lrng_drng_instances();
+	u32 node;
+
+	if (!lrng_drng) {
+		lrng_drng_init.force_reseed = true;
+		pr_debug("force reseed of initial DRNG\n");
+		return;
+	}
+	for_each_online_node(node) {
+		struct lrng_drng *drng = lrng_drng[node];
+
+		if (!drng)
+			continue;
+
+		drng->force_reseed = true;
+		pr_debug("force reseed of DRNG on node %u\n", node);
+	}
+	lrng_drng_atomic.force_reseed = true;
+}
+
+/**
+ * lrng_drng_get() - Get random data out of the DRNG which is reseeded
+ * frequently.
+ *
+ * @outbuf: buffer for storing random data
+ * @outbuflen: length of outbuf
+ *
+ * Return:
+ * * < 0 in error case (DRNG generation or update failed)
+ * * >=0 returning the returned number of bytes
+ */
+static int lrng_drng_get(struct lrng_drng *drng, u8 *outbuf, u32 outbuflen)
+{
+	unsigned long flags = 0;
+	u32 processed = 0;
+
+	if (!outbuf || !outbuflen)
+		return 0;
+
+	outbuflen = min_t(size_t, outbuflen, INT_MAX);
+
+	lrng_drngs_init_cc20();
+
+	while (outbuflen) {
+		u32 todo = min_t(u32, outbuflen, LRNG_DRNG_MAX_REQSIZE);
+		int ret;
+
+		/* All but the atomic DRNG are seeded during generation */
+		if (atomic_dec_and_test(&drng->requests) ||
+		    drng->force_reseed ||
+		    time_after(jiffies, drng->last_seeded +
+			       lrng_drng_reseed_max_time * HZ)) {
+			if (likely(drng != &lrng_drng_atomic)) {
+				if (lrng_pool_trylock())
+					atomic_set(&drng->requests, 1);
+				else
+					lrng_drng_seed(drng);
+			}
+		}
+
+		lrng_drng_lock(drng, &flags);
+		ret = drng->crypto_cb->lrng_drng_generate_helper(
+					drng->drng, outbuf + processed, todo);
+		lrng_drng_unlock(drng, &flags);
+		if (ret <= 0) {
+			pr_warn("getting random data from DRNG failed (%d)\n",
+				ret);
+			return -EFAULT;
+		}
+		processed += ret;
+		outbuflen -= ret;
+	}
+
+	return processed;
+}
+
+int lrng_drng_get_atomic(u8 *outbuf, u32 outbuflen)
+{
+	return lrng_drng_get(&lrng_drng_atomic, outbuf, outbuflen);
+}
+
+int lrng_drng_get_sleep(u8 *outbuf, u32 outbuflen)
+{
+	struct lrng_drng **lrng_drng = lrng_drng_instances();
+	struct lrng_drng *drng = &lrng_drng_init;
+	int node = numa_node_id();
+
+	might_sleep();
+
+	if (lrng_drng && lrng_drng[node] && lrng_drng[node]->fully_seeded)
+		drng = lrng_drng[node];
+
+	return lrng_drng_get(drng, outbuf, outbuflen);
+}
+
+/* Initialize the default DRNG during boot */
+void lrng_drngs_init_cc20(void)
+{
+	unsigned long flags = 0;
+
+	if (lrng_get_available())
+		return;
+
+	lrng_drng_lock(&lrng_drng_init, &flags);
+	if (lrng_get_available()) {
+		lrng_drng_unlock(&lrng_drng_init, &flags);
+		return;
+	}
+
+	lrng_drng_reset(&lrng_drng_init);
+	lrng_cc20_init_state(&chacha20);
+	lrng_state_init_seed_work();
+	lrng_drng_unlock(&lrng_drng_init, &flags);
+
+	lrng_drng_lock(&lrng_drng_atomic, &flags);
+	lrng_drng_reset(&lrng_drng_atomic);
+	/*
+	 * We do not initialize the state of the atomic DRNG as it is identical
+	 * to the DRNG at this point.
+	 */
+	lrng_drng_unlock(&lrng_drng_atomic, &flags);
+
+	lrng_set_available();
+}
+
+/* Reset LRNG such that all existing entropy is gone */
+static void _lrng_reset(struct work_struct *work)
+{
+	struct lrng_drng **lrng_drng = lrng_drng_instances();
+	unsigned long flags = 0;
+
+	if (!lrng_drng) {
+		lrng_drng_lock(&lrng_drng_init, &flags);
+		lrng_drng_reset(&lrng_drng_init);
+		lrng_drng_unlock(&lrng_drng_init, &flags);
+	} else {
+		u32 node;
+
+		for_each_online_node(node) {
+			struct lrng_drng *drng = lrng_drng[node];
+
+			if (!drng)
+				continue;
+			lrng_drng_lock(drng, &flags);
+			lrng_drng_reset(drng);
+			lrng_drng_unlock(drng, &flags);
+		}
+	}
+	lrng_set_entropy_thresh(LRNG_INIT_ENTROPY_BITS +
+				LRNG_CONDITIONING_ENTROPY_LOSS);
+
+	lrng_reset_state();
+}
+
+static DECLARE_WORK(lrng_reset_work, _lrng_reset);
+
+void lrng_reset(void)
+{
+	schedule_work(&lrng_reset_work);
+}
+
+/***************************** Initialize LRNG *******************************/
+
+static int __init lrng_init(void)
+{
+	lrng_drngs_init_cc20();
+
+	lrng_drngs_numa_alloc();
+	return 0;
+}
+
+late_initcall(lrng_init);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
+MODULE_DESCRIPTION("Linux Random Number Generator");
diff --git a/drivers/char/lrng/lrng_interfaces.c b/drivers/char/lrng/lrng_interfaces.c
new file mode 100644
index 000000000000..d6ddc72fc9b7
--- /dev/null
+++ b/drivers/char/lrng/lrng_interfaces.c
@@ -0,0 +1,638 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG User and kernel space interfaces
+ *
+ * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/freezer.h>
+#include <linux/fs.h>
+#include <linux/genhd.h>
+#include <linux/kthread.h>
+#include <linux/poll.h>
+#include <linux/preempt.h>
+#include <linux/random.h>
+#include <linux/slab.h>
+#include <linux/syscalls.h>
+#include <linux/timex.h>
+
+#include "lrng_internal.h"
+
+/*
+ * If the entropy count falls under this number of bits, then we
+ * should wake up processes which are selecting or polling on write
+ * access to /dev/random.
+ */
+u32 lrng_write_wakeup_bits = LRNG_WRITE_WAKEUP_ENTROPY;
+
+static LIST_HEAD(lrng_ready_list);
+static DEFINE_SPINLOCK(lrng_ready_list_lock);
+
+static DECLARE_WAIT_QUEUE_HEAD(lrng_write_wait);
+static DECLARE_WAIT_QUEUE_HEAD(lrng_init_wait);
+static struct fasync_struct *fasync;
+
+struct ctl_table random_table[];
+/********************************** Helper ***********************************/
+
+/* Is the DRNG seed level too low? */
+static inline bool lrng_need_entropy(void)
+{
+	return (lrng_avail_entropy() < lrng_write_wakeup_bits);
+}
+
+void lrng_writer_wakeup(void)
+{
+	if (lrng_need_entropy() && wq_has_sleeper(&lrng_write_wait)) {
+		wake_up_interruptible(&lrng_write_wait);
+		kill_fasync(&fasync, SIGIO, POLL_OUT);
+	}
+}
+
+void lrng_init_wakeup(void)
+{
+	wake_up_all(&lrng_init_wait);
+	kill_fasync(&fasync, SIGIO, POLL_IN);
+}
+
+/**
+ * lrng_process_ready_list() - Ping all kernel internal callers waiting until
+ * the DRNG is at least minimally seeded to inform that the DRNG reached that
+ * seed level.
+ *
+ * When the SP800-90B testing is enabled, the ping only happens if the SP800-90B
+ * startup health tests are completed. This implies that kernel internal
+ * callers always have an SP800-90B compliant noise source when being
+ * pinged.
+ */
+void lrng_process_ready_list(void)
+{
+	unsigned long flags;
+	struct random_ready_callback *rdy, *tmp;
+
+	if (!lrng_sp80090b_startup_complete())
+		return;
+
+	spin_lock_irqsave(&lrng_ready_list_lock, flags);
+	list_for_each_entry_safe(rdy, tmp, &lrng_ready_list, list) {
+		struct module *owner = rdy->owner;
+
+		list_del_init(&rdy->list);
+		rdy->func(rdy);
+		module_put(owner);
+	}
+	spin_unlock_irqrestore(&lrng_ready_list_lock, flags);
+}
+
+void lrng_debug_report_seedlevel(const char *name)
+{
+#ifdef CONFIG_WARN_ALL_UNSEEDED_RANDOM
+	static void *previous = NULL;
+	void *caller = (void *) _RET_IP_;
+
+	if (READ_ONCE(previous) == caller)
+		return;
+
+	if (!lrng_state_min_seeded())
+		pr_notice("%pS %s called without reaching mimimally seeded "
+			  "level (available entropy %u)\n", caller, name,
+			  lrng_avail_entropy());
+
+	WRITE_ONCE(previous, caller);
+#endif
+}
+
+/************************ LRNG kernel input interfaces ************************/
+
+/**
+ * add_hwgenerator_randomness() - Interface for in-kernel drivers of true
+ * hardware RNGs.
+ *
+ * Those devices may produce endless random bits and will be throttled
+ * when our pool is full.
+ *
+ * @buffer: buffer holding the entropic data from HW noise sources to be used to
+ *	    insert into entropy pool.
+ * @count: length of buffer
+ * @entropy_bits: amount of entropy in buffer (value is in bits)
+ */
+void add_hwgenerator_randomness(const char *buffer, size_t count,
+				size_t entropy_bits)
+{
+	/*
+	 * Suspend writing if we are fully loaded with entropy.
+	 * We'll be woken up again once below lrng_write_wakeup_thresh,
+	 * or when the calling thread is about to terminate.
+	 */
+	wait_event_interruptible(lrng_write_wait,
+				lrng_need_entropy() ||
+				lrng_state_exseed_allow(lrng_noise_source_hw) ||
+				kthread_should_stop());
+	lrng_state_exseed_set(lrng_noise_source_hw, false);
+	lrng_pool_lfsr_nonaligned(buffer, count);
+	lrng_pool_add_entropy(entropy_bits);
+}
+EXPORT_SYMBOL_GPL(add_hwgenerator_randomness);
+
+/**
+ * add_bootloader_randomness() - Handle random seed passed by bootloader.
+ *
+ * If the seed is trustworthy, it would be regarded as hardware RNGs. Otherwise
+ * it would be regarded as device data.
+ * The decision is controlled by CONFIG_RANDOM_TRUST_BOOTLOADER.
+ *
+ * @buf: buffer holding the entropic data from HW noise sources to be used to
+ *	 insert into entropy pool.
+ * @size: length of buffer
+ */
+void add_bootloader_randomness(const void *buf, unsigned int size)
+{
+	if (IS_ENABLED(CONFIG_RANDOM_TRUST_BOOTLOADER))
+		add_hwgenerator_randomness(buf, size, size * 8);
+	else
+		add_device_randomness(buf, size);
+}
+EXPORT_SYMBOL_GPL(add_bootloader_randomness);
+
+/*
+ * Callback for HID layer -- use the HID event values to stir the entropy pool
+ */
+void add_input_randomness(unsigned int type, unsigned int code,
+			  unsigned int value)
+{
+	static unsigned char last_value;
+
+	/* ignore autorepeat and the like */
+	if (value == last_value)
+		return;
+
+	last_value = value;
+
+	lrng_pool_lfsr_u32((type << 4) ^ code ^ (code >> 4) ^ value);
+}
+EXPORT_SYMBOL_GPL(add_input_randomness);
+
+/**
+ * add_device_randomness() - Add device- or boot-specific data to the entropy
+ * pool to help initialize it.
+ *
+ * None of this adds any entropy; it is meant to avoid the problem of
+ * the entropy pool having similar initial state across largely
+ * identical devices.
+ *
+ * @buf: buffer holding the entropic data from HW noise sources to be used to
+ *	 insert into entropy pool.
+ * @size: length of buffer
+ */
+void add_device_randomness(const void *buf, unsigned int size)
+{
+	lrng_pool_lfsr_nonaligned((u8 *)buf, size);
+	lrng_pool_lfsr_u32(random_get_entropy());
+	lrng_pool_lfsr_u32(jiffies);
+}
+EXPORT_SYMBOL(add_device_randomness);
+
+#ifdef CONFIG_BLOCK
+void rand_initialize_disk(struct gendisk *disk) { }
+void add_disk_randomness(struct gendisk *disk) { }
+EXPORT_SYMBOL(add_disk_randomness);
+#endif
+
+/**
+ * del_random_ready_callback() - Delete a previously registered readiness
+ * callback function.
+ *
+ * @rdy: callback definition that was registered initially
+ */
+void del_random_ready_callback(struct random_ready_callback *rdy)
+{
+	unsigned long flags;
+	struct module *owner = NULL;
+
+	spin_lock_irqsave(&lrng_ready_list_lock, flags);
+	if (!list_empty(&rdy->list)) {
+		list_del_init(&rdy->list);
+		owner = rdy->owner;
+	}
+	spin_unlock_irqrestore(&lrng_ready_list_lock, flags);
+
+	module_put(owner);
+}
+EXPORT_SYMBOL(del_random_ready_callback);
+
+/**
+ * add_random_ready_callback() - Add a callback function that will be invoked
+ * when the DRNG is mimimally seeded.
+ *
+ * @rdy: callback definition to be invoked when the LRNG is seeded
+ *
+ * Return:
+ * * 0 if callback is successfully added
+ * * -EALREADY if pool is already initialised (callback not called)
+ * * -ENOENT if module for callback is not alive
+ */
+int add_random_ready_callback(struct random_ready_callback *rdy)
+{
+	struct module *owner;
+	unsigned long flags;
+	int err = -EALREADY;
+
+	if (likely(lrng_state_min_seeded()))
+		return err;
+
+	owner = rdy->owner;
+	if (!try_module_get(owner))
+		return -ENOENT;
+
+	spin_lock_irqsave(&lrng_ready_list_lock, flags);
+	if (lrng_state_min_seeded())
+		goto out;
+
+	owner = NULL;
+
+	list_add(&rdy->list, &lrng_ready_list);
+	err = 0;
+
+out:
+	spin_unlock_irqrestore(&lrng_ready_list_lock, flags);
+
+	module_put(owner);
+
+	return err;
+}
+EXPORT_SYMBOL(add_random_ready_callback);
+
+/*********************** LRNG kernel output interfaces ************************/
+
+/**
+ * get_random_bytes() - Provider of cryptographic strong random numbers for
+ * kernel-internal usage.
+ *
+ * This function is appropriate for all in-kernel use cases. However,
+ * it will always use the ChaCha20 DRNG.
+ *
+ * @buf: buffer to store the random bytes
+ * @nbytes: size of the buffer
+ */
+void get_random_bytes(void *buf, int nbytes)
+{
+	lrng_drng_get_atomic((u8 *)buf, (u32)nbytes);
+	lrng_debug_report_seedlevel("get_random_bytes");
+}
+EXPORT_SYMBOL(get_random_bytes);
+
+/**
+ * get_random_bytes_full() - Provider of cryptographic strong random numbers
+ * for kernel-internal usage.
+ *
+ * This function is appropriate only for non-atomic use cases as this
+ * function may sleep. Though, it provides access to the full functionality
+ * of LRNG including the switchable DRNG support, that may support other
+ * DRNGs such as the SP800-90A DRBG.
+ *
+ * @buf: buffer to store the random bytes
+ * @nbytes: size of the buffer
+ */
+void get_random_bytes_full(void *buf, int nbytes)
+{
+	lrng_drng_get_sleep((u8 *)buf, (u32)nbytes);
+	lrng_debug_report_seedlevel("get_random_bytes_full");
+}
+EXPORT_SYMBOL(get_random_bytes_full);
+
+/**
+ * wait_for_random_bytes() - Wait for the LRNG to be seeded and thus
+ * guaranteed to supply cryptographically secure random numbers.
+ *
+ * This applies to: the /dev/urandom device, the get_random_bytes function,
+ * and the get_random_{u32,u64,int,long} family of functions. Using any of
+ * these functions without first calling this function forfeits the guarantee
+ * of security.
+ *
+ * Return:
+ * * 0 if the LRNG has been seeded.
+ * * -ERESTARTSYS if the function was interrupted by a signal.
+ */
+int wait_for_random_bytes(void)
+{
+	if (likely(lrng_state_min_seeded()))
+		return 0;
+	return wait_event_interruptible(lrng_init_wait,
+					lrng_state_min_seeded());
+}
+EXPORT_SYMBOL(wait_for_random_bytes);
+
+/**
+ * get_random_bytes_arch() - This function will use the architecture-specific
+ * hardware random number generator if it is available.
+ *
+ * The arch-specific hw RNG will almost certainly be faster than what we can
+ * do in software, but it is impossible to verify that it is implemented
+ * securely (as opposed, to, say, the AES encryption of a sequence number using
+ * a key known by the NSA).  So it's useful if we need the speed, but only if
+ * we're willing to trust the hardware manufacturer not to have put in a back
+ * door.
+ *
+ * @buf: buffer allocated by caller to store the random data in
+ * @nbytes: length of outbuf
+ *
+ * Return: number of bytes filled in.
+ */
+int __must_check get_random_bytes_arch(void *buf, int nbytes)
+{
+	u8 *p = buf;
+
+	while (nbytes) {
+		unsigned long v;
+		int chunk = min_t(int, nbytes, sizeof(unsigned long));
+
+		if (!arch_get_random_long(&v))
+			break;
+
+		memcpy(p, &v, chunk);
+		p += chunk;
+		nbytes -= chunk;
+	}
+
+	if (nbytes)
+		lrng_drng_get_atomic((u8 *)p, (u32)nbytes);
+
+	return nbytes;
+}
+EXPORT_SYMBOL(get_random_bytes_arch);
+
+/************************ LRNG user output interfaces *************************/
+
+static ssize_t lrng_read_common(char __user *buf, size_t nbytes)
+{
+	ssize_t ret = 0;
+	u8 tmpbuf[LRNG_DRNG_BLOCKSIZE] __aligned(LRNG_KCAPI_ALIGN);
+	u8 *tmp_large = NULL, *tmp = tmpbuf;
+	u32 tmplen = sizeof(tmpbuf);
+
+	if (nbytes == 0)
+		return 0;
+
+	/*
+	 * Satisfy large read requests -- as the common case are smaller
+	 * request sizes, such as 16 or 32 bytes, avoid a kmalloc overhead for
+	 * those by using the stack variable of tmpbuf.
+	 */
+	if (!IS_ENABLED(CONFIG_BASE_SMALL) && (nbytes > sizeof(tmpbuf))) {
+		tmplen = min_t(u32, nbytes, LRNG_DRNG_MAX_REQSIZE);
+		tmp_large = kmalloc(tmplen + LRNG_KCAPI_ALIGN, GFP_KERNEL);
+		if (!tmp_large)
+			tmplen = sizeof(tmpbuf);
+		else
+			tmp = PTR_ALIGN(tmp_large, LRNG_KCAPI_ALIGN);
+	}
+
+	while (nbytes) {
+		u32 todo = min_t(u32, nbytes, tmplen);
+		int rc = 0;
+
+		/* Reschedule if we received a large request. */
+		if ((tmp_large) && need_resched()) {
+			if (signal_pending(current)) {
+				if (ret == 0)
+					ret = -ERESTARTSYS;
+				break;
+			}
+			schedule();
+		}
+
+		rc = lrng_drng_get_sleep(tmp, todo);
+		if (rc <= 0) {
+			if (rc < 0)
+				ret = rc;
+			break;
+		}
+		if (copy_to_user(buf, tmp, rc)) {
+			ret = -EFAULT;
+			break;
+		}
+
+		nbytes -= rc;
+		buf += rc;
+		ret += rc;
+	}
+
+	/* Wipe data just returned from memory */
+	if (tmp_large)
+		kzfree(tmp_large);
+	else
+		memzero_explicit(tmpbuf, sizeof(tmpbuf));
+
+	return ret;
+}
+
+static ssize_t
+lrng_read_common_block(int nonblock, char __user *buf, size_t nbytes)
+{
+	if (nbytes == 0)
+		return 0;
+
+	if (unlikely(!lrng_state_operational())) {
+		int ret;
+
+		if (nonblock)
+			return -EAGAIN;
+
+		ret = wait_event_interruptible(lrng_init_wait,
+					       lrng_state_operational());
+		if (unlikely(ret))
+			return ret;
+	}
+
+	return lrng_read_common(buf, nbytes);
+}
+
+static ssize_t lrng_drng_read_block(struct file *file, char __user *buf,
+				     size_t nbytes, loff_t *ppos)
+{
+	return lrng_read_common_block(file->f_flags & O_NONBLOCK, buf, nbytes);
+}
+
+static unsigned int lrng_random_poll(struct file *file, poll_table *wait)
+{
+	__poll_t mask;
+
+	poll_wait(file, &lrng_init_wait, wait);
+	poll_wait(file, &lrng_write_wait, wait);
+	mask = 0;
+	if (lrng_state_operational())
+		mask |= EPOLLIN | EPOLLRDNORM;
+	if (lrng_need_entropy() ||
+	    lrng_state_exseed_allow(lrng_noise_source_user))
+		mask |= EPOLLOUT | EPOLLWRNORM;
+	return mask;
+}
+
+static ssize_t lrng_drng_write_common(const char __user *buffer, size_t count,
+				      u32 entropy_bits)
+{
+	ssize_t ret = 0;
+	u8 buf[64] __aligned(LRNG_KCAPI_ALIGN);
+	const char __user *p = buffer;
+	u32 orig_entropy_bits = entropy_bits;
+
+	if (!lrng_get_available())
+		return -EAGAIN;
+
+	count = min_t(size_t, count, INT_MAX);
+	while (count > 0) {
+		size_t bytes = min_t(size_t, count, sizeof(buf));
+		u32 ent = min_t(u32, bytes<<3, entropy_bits);
+
+		if (copy_from_user(&buf, p, bytes))
+			return -EFAULT;
+		/* Inject data into entropy pool */
+		lrng_pool_lfsr(buf, bytes);
+		lrng_pool_add_entropy(ent);
+
+		count -= bytes;
+		p += bytes;
+		ret += bytes;
+		entropy_bits -= ent;
+
+		cond_resched();
+	}
+
+	/* Force reseed of DRNG during next data request. */
+	if (!orig_entropy_bits)
+		lrng_drng_force_reseed();
+
+	return ret;
+}
+
+static ssize_t lrng_drng_read(struct file *file, char __user *buf,
+			      size_t nbytes, loff_t *ppos)
+{
+	if (!lrng_state_min_seeded())
+		pr_notice_ratelimited("%s - use of insufficiently seeded DRNG "
+				      "(%zu bytes read)\n", current->comm,
+				      nbytes);
+	else if (!lrng_state_operational())
+		pr_debug_ratelimited("%s - use of not fully seeded DRNG (%zu "
+				     "bytes read)\n", current->comm, nbytes);
+
+	return lrng_read_common(buf, nbytes);
+}
+
+static ssize_t lrng_drng_write(struct file *file, const char __user *buffer,
+			       size_t count, loff_t *ppos)
+{
+	return lrng_drng_write_common(buffer, count, 0);
+}
+
+static long lrng_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
+{
+	int size, ent_count_bits;
+	int __user *p = (int __user *)arg;
+
+	switch (cmd) {
+	case RNDGETENTCNT:
+		ent_count_bits = lrng_avail_entropy();
+		if (put_user(ent_count_bits, p))
+			return -EFAULT;
+		return 0;
+	case RNDADDTOENTCNT:
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+		if (get_user(ent_count_bits, p))
+			return -EFAULT;
+		ent_count_bits = (int)lrng_avail_entropy() + ent_count_bits;
+		if (ent_count_bits < 0)
+			ent_count_bits = 0;
+		if (ent_count_bits > LRNG_POOL_SIZE_BITS)
+			ent_count_bits = LRNG_POOL_SIZE_BITS;
+		lrng_pool_set_entropy(ent_count_bits);
+		return 0;
+	case RNDADDENTROPY:
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+		if (get_user(ent_count_bits, p++))
+			return -EFAULT;
+		if (ent_count_bits < 0)
+			return -EINVAL;
+		if (get_user(size, p++))
+			return -EFAULT;
+		if (size < 0)
+			return -EINVAL;
+		lrng_state_exseed_set(lrng_noise_source_user, false);
+		/* there cannot be more entropy than data */
+		ent_count_bits = min(ent_count_bits, size<<3);
+		return lrng_drng_write_common((const char __user *)p, size,
+					      ent_count_bits);
+	case RNDZAPENTCNT:
+	case RNDCLEARPOOL:
+		/* Clear the entropy pool counter. */
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+		lrng_pool_set_entropy(0);
+		return 0;
+	case RNDRESEEDCRNG:
+		/*
+		 * We leave the capability check here since it is present
+		 * in the upstream's RNG implementation. Yet, user space
+		 * can trigger a reseed as easy as writing into /dev/random
+		 * or /dev/urandom where no privilege is needed.
+		 */
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+		/* Force a reseed of all DRNGs */
+		lrng_drng_force_reseed();
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
+static int lrng_fasync(int fd, struct file *filp, int on)
+{
+	return fasync_helper(fd, filp, on, &fasync);
+}
+
+const struct file_operations random_fops = {
+	.read  = lrng_drng_read_block,
+	.write = lrng_drng_write,
+	.poll  = lrng_random_poll,
+	.unlocked_ioctl = lrng_ioctl,
+	.compat_ioctl = compat_ptr_ioctl,
+	.fasync = lrng_fasync,
+	.llseek = noop_llseek,
+};
+
+const struct file_operations urandom_fops = {
+	.read  = lrng_drng_read,
+	.write = lrng_drng_write,
+	.unlocked_ioctl = lrng_ioctl,
+	.compat_ioctl = compat_ptr_ioctl,
+	.fasync = lrng_fasync,
+	.llseek = noop_llseek,
+};
+
+SYSCALL_DEFINE3(getrandom, char __user *, buf, size_t, count,
+		unsigned int, flags)
+{
+	if (flags & ~(GRND_NONBLOCK|GRND_RANDOM|GRND_INSECURE))
+		return -EINVAL;
+
+	/*
+	 * Requesting insecure and blocking randomness at the same time makes
+	 * no sense.
+	 */
+	if ((flags &
+	     (GRND_INSECURE|GRND_RANDOM)) == (GRND_INSECURE|GRND_RANDOM))
+		return -EINVAL;
+
+	if (count > INT_MAX)
+		count = INT_MAX;
+
+	if (flags & GRND_INSECURE)
+		return lrng_drng_read(NULL, buf, count, NULL);
+
+	return lrng_read_common_block(flags & GRND_NONBLOCK, buf, count);
+}
diff --git a/drivers/char/lrng/lrng_internal.h b/drivers/char/lrng/lrng_internal.h
new file mode 100644
index 000000000000..edf38121ec65
--- /dev/null
+++ b/drivers/char/lrng/lrng_internal.h
@@ -0,0 +1,296 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
+/*
+ * Copyright (C) 2018 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#ifndef _LRNG_INTERNAL_H
+#define _LRNG_INTERNAL_H
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+
+/*************************** General LRNG parameter ***************************/
+
+/* Entropy pool parameter
+ *
+ * The LRNG_POOL_SIZE cannot be smaller than 64 bytes as the SHA-1 operation
+ * in lrng_chacha20.c requires multiples of 64 bytes
+ */
+#define LRNG_POOL_SIZE			(16 << CONFIG_LRNG_POOL_SIZE)
+#define LRNG_POOL_WORD_BYTES		(4)	/* (sizeof(atomic_t)) */
+#define LRNG_POOL_SIZE_BYTES		(LRNG_POOL_SIZE * LRNG_POOL_WORD_BYTES)
+#define LRNG_POOL_SIZE_BITS		(LRNG_POOL_SIZE_BYTES * 8)
+#define LRNG_POOL_WORD_BITS		(LRNG_POOL_WORD_BYTES * 8)
+
+/* Security strength of LRNG -- this must match DRNG security strength */
+#define LRNG_DRNG_SECURITY_STRENGTH_BYTES 32
+#define LRNG_DRNG_SECURITY_STRENGTH_BITS (LRNG_DRNG_SECURITY_STRENGTH_BYTES * 8)
+#define LRNG_DRNG_BLOCKSIZE 64		/* Maximum of DRNG block sizes */
+
+/*
+ * SP800-90A defines a maximum request size of 1<<16 bytes. The given value is
+ * considered a safer margin.
+ *
+ * This value is allowed to be changed.
+ */
+#define LRNG_DRNG_MAX_REQSIZE		(1<<12)
+
+/*
+ * SP800-90A defines a maximum number of requests between reseeds of 2^48.
+ * The given value is considered a much safer margin, balancing requests for
+ * frequent reseeds with the need to conserve entropy. This value MUST NOT be
+ * larger than INT_MAX because it is used in an atomic_t.
+ *
+ * This value is allowed to be changed.
+ */
+#define LRNG_DRNG_RESEED_THRESH		(1<<20)
+
+/*
+ * Number of interrupts to be recorded to assume that DRNG security strength
+ * bits of entropy are received.
+ * Note: a value below the DRNG security strength should not be defined as this
+ *	 may imply the DRNG can never be fully seeded in case other noise
+ *	 sources are unavailable.
+ *
+ * This value is allowed to be changed.
+ */
+#define LRNG_IRQ_ENTROPY_BITS		LRNG_DRNG_SECURITY_STRENGTH_BITS
+
+/*
+ * Min required seed entropy is 128 bits covering the minimum entropy
+ * requirement of SP800-131A and the German BSI's TR02102.
+ *
+ * This value is allowed to be changed.
+ */
+#define LRNG_FULL_SEED_ENTROPY_BITS	LRNG_DRNG_SECURITY_STRENGTH_BITS
+#define LRNG_MIN_SEED_ENTROPY_BITS	128
+#define LRNG_INIT_ENTROPY_BITS		32
+
+/*
+ * Amount of entropy that is lost with the conditioning functions of LFSR and
+ * hash_df as shown with the entropy analysis compliant to SP800-90B.
+ */
+#define LRNG_CONDITIONING_ENTROPY_LOSS	1
+
+/*
+ * Wakeup value
+ *
+ * This value is allowed to be changed.
+ */
+#if (LRNG_POOL_SIZE_BITS <= (LRNG_DRNG_SECURITY_STRENGTH_BITS * 2))
+# define LRNG_WRITE_WAKEUP_ENTROPY	(LRNG_DRNG_SECURITY_STRENGTH_BITS + \
+					LRNG_CONDITIONING_ENTROPY_LOSS)
+#else
+# define LRNG_WRITE_WAKEUP_ENTROPY	(LRNG_DRNG_SECURITY_STRENGTH_BITS * 2)
+#endif
+
+/*
+ * Oversampling factor of IRQ events to obtain
+ * LRNG_DRNG_SECURITY_STRENGTH_BYTES. This factor is used when a
+ * high-resolution time stamp is not available. In this case, jiffies and
+ * register contents are used to fill the entropy pool. These noise sources
+ * are much less entropic than the high-resolution timer. The entropy content
+ * is the entropy content assumed with LRNG_IRQ_ENTROPY_BITS divided by
+ * LRNG_IRQ_OVERSAMPLING_FACTOR.
+ *
+ * This value is allowed to be changed.
+ */
+#define LRNG_IRQ_OVERSAMPLING_FACTOR	10
+
+/*
+ * Alignmask which should cover all cipher implementations
+ * WARNING: If this is changed to a value larger than 8, manual
+ * alignment is necessary as older versions of GCC may not be capable
+ * of aligning stack variables at boundaries greater than 8.
+ * In this case, PTR_ALIGN must be used.
+ */
+#define LRNG_KCAPI_ALIGN		8
+
+/************************ Default DRNG implementation *************************/
+
+extern struct chacha20_state chacha20;
+extern const struct lrng_crypto_cb lrng_cc20_crypto_cb;
+void lrng_cc20_init_state(struct chacha20_state *state);
+
+/********************************** /proc *************************************/
+
+static inline void lrng_pool_inc_numa_node(void) { }
+
+/****************************** LRNG interfaces *******************************/
+
+extern u32 lrng_write_wakeup_bits;
+extern int lrng_drng_reseed_max_time;
+
+void lrng_writer_wakeup(void);
+void lrng_init_wakeup(void);
+void lrng_debug_report_seedlevel(const char *name);
+void lrng_process_ready_list(void);
+
+/************************** Entropy pool management ***************************/
+
+enum lrng_external_noise_source {
+	lrng_noise_source_hw,
+	lrng_noise_source_user
+};
+
+bool lrng_state_exseed_allow(enum lrng_external_noise_source source);
+void lrng_state_exseed_set(enum lrng_external_noise_source source, bool type);
+void lrng_state_init_seed_work(void);
+u32 lrng_avail_entropy(void);
+void lrng_set_entropy_thresh(u32 new);
+int lrng_pool_trylock(void);
+void lrng_pool_unlock(void);
+void lrng_reset_state(void);
+void lrng_pool_all_numa_nodes_seeded(void);
+bool lrng_state_min_seeded(void);
+bool lrng_state_fully_seeded(void);
+bool lrng_state_operational(void);
+bool lrng_pool_highres_timer(void);
+void lrng_pool_set_entropy(u32 entropy_bits);
+void lrng_pool_lfsr(const u8 *buf, u32 buflen);
+void lrng_pool_lfsr_nonaligned(const u8 *buf, u32 buflen);
+void lrng_pool_lfsr_u32(u32 value);
+void lrng_pool_add_irq(u32 irq_num);
+void lrng_pool_add_entropy(u32 entropy_bits);
+
+struct entropy_buf {
+	u8 a[LRNG_DRNG_SECURITY_STRENGTH_BYTES];
+	u8 b[LRNG_DRNG_SECURITY_STRENGTH_BYTES];
+	u8 c[LRNG_DRNG_SECURITY_STRENGTH_BYTES];
+	u32 now;
+};
+
+int lrng_fill_seed_buffer(const struct lrng_crypto_cb *crypto_cb, void *hash,
+			  struct entropy_buf *entropy_buf, u32 entropy_retain);
+void lrng_init_ops(u32 seed_bits);
+
+/************************** Jitter RNG Noise Source ***************************/
+
+#ifdef CONFIG_LRNG_JENT
+u32 lrng_get_jent(u8 *outbuf, unsigned int outbuflen);
+u32 lrng_jent_entropylevel(void);
+#else /* CONFIG_CRYPTO_JITTERENTROPY */
+static inline u32 lrng_get_jent(u8 *outbuf, unsigned int outbuflen) {return 0; }
+static inline u32 lrng_jent_entropylevel(void) { return 0; }
+#endif /* CONFIG_CRYPTO_JITTERENTROPY */
+
+/*************************** CPU-based Noise Source ***************************/
+
+u32 lrng_get_arch(u8 *outbuf);
+u32 lrng_slow_noise_req_entropy(u32 required_entropy_bits);
+
+/****************************** DRNG processing *******************************/
+
+/* Secondary DRNG state handle */
+struct lrng_drng {
+	void *drng;				/* DRNG handle */
+	void *hash;				/* Hash handle */
+	const struct lrng_crypto_cb *crypto_cb;	/* Crypto callbacks */
+	atomic_t requests;			/* Number of DRNG requests */
+	unsigned long last_seeded;		/* Last time it was seeded */
+	bool fully_seeded;			/* Is DRNG fully seeded? */
+	bool force_reseed;			/* Force a reseed */
+	struct mutex lock;
+	spinlock_t spin_lock;
+};
+
+extern struct mutex lrng_crypto_cb_update;
+
+struct lrng_drng *lrng_drng_init_instance(void);
+struct lrng_drng *lrng_drng_atomic_instance(void);
+
+static __always_inline bool lrng_drng_is_atomic(struct lrng_drng *drng)
+{
+	return (drng->drng == lrng_drng_atomic_instance()->drng);
+}
+
+/* Lock the DRNG */
+static __always_inline void lrng_drng_lock(struct lrng_drng *drng,
+					   unsigned long *flags)
+{
+	/* Use spin lock in case the atomic DRNG context is used */
+	if (lrng_drng_is_atomic(drng)) {
+		spin_lock_irqsave(&drng->spin_lock, *flags);
+
+		/*
+		 * In case a lock transition happened while we were spinning,
+		 * catch this case and use the new lock type.
+		 */
+		if (!lrng_drng_is_atomic(drng)) {
+			spin_unlock_irqrestore(&drng->spin_lock, *flags);
+			mutex_lock(&drng->lock);
+		}
+	} else {
+		mutex_lock(&drng->lock);
+	}
+}
+
+/* Unlock the DRNG */
+static __always_inline void lrng_drng_unlock(struct lrng_drng *drng,
+					     unsigned long *flags)
+{
+	if (lrng_drng_is_atomic(drng))
+		spin_unlock_irqrestore(&drng->spin_lock, *flags);
+	else
+		mutex_unlock(&drng->lock);
+}
+
+bool lrng_get_available(void);
+void lrng_set_available(void);
+void lrng_drngs_init_cc20(void);
+void lrng_drng_reset(struct lrng_drng *drng);
+int lrng_drng_get_atomic(u8 *outbuf, u32 outbuflen);
+int lrng_drng_get_sleep(u8 *outbuf, u32 outbuflen);
+void lrng_drng_force_reseed(void);
+void lrng_drng_seed_work(struct work_struct *dummy);
+
+static inline struct lrng_drng **lrng_drng_instances(void) { return NULL; }
+static inline void lrng_drngs_numa_alloc(void) { return; }
+
+/************************** Health Test linking code **************************/
+
+enum lrng_health_res {
+	lrng_health_pass,		/* Health test passes on time stamp */
+	lrng_health_fail_use,		/* Time stamp unhealthy, but mix in */
+	lrng_health_fail_drop		/* Time stamp unhealthy, drop it */
+};
+
+#ifdef CONFIG_LRNG_HEALTH_TESTS
+bool lrng_sp80090b_startup_complete(void);
+bool lrng_sp80090b_compliant(void);
+
+enum lrng_health_res lrng_health_test(u32 now_time);
+void lrng_health_disable(void);
+
+void lrng_reset(void);
+#else	/* CONFIG_LRNG_HEALTH_TESTS */
+static inline bool lrng_sp80090b_startup_complete(void) { return true; }
+static inline bool lrng_sp80090b_compliant(void) { return false; }
+
+static inline enum lrng_health_res
+lrng_health_test(u32 now_time) { return lrng_health_pass; }
+static inline void lrng_health_disable(void) { }
+#endif	/* CONFIG_LRNG_HEALTH_TESTS */
+
+/****************************** Helper code ***********************************/
+
+static inline u32 atomic_read_u32(atomic_t *v)
+{
+	return (u32)atomic_read(v);
+}
+
+/*************************** Auxiliary functions ******************************/
+
+void invalidate_batched_entropy(void);
+
+/***************************** Testing code ***********************************/
+
+#ifdef CONFIG_LRNG_TESTING
+bool lrng_raw_entropy_store(u32 value);
+#else	/* CONFIG_LRNG_TESTING */
+static inline bool lrng_raw_entropy_store(u32 value) { return false; }
+#endif	/* CONFIG_LRNG_TESTING */
+
+#endif /* _LRNG_INTERNAL_H */
diff --git a/drivers/char/lrng/lrng_lfsr.h b/drivers/char/lrng/lrng_lfsr.h
new file mode 100644
index 000000000000..f0e38a0aadfd
--- /dev/null
+++ b/drivers/char/lrng/lrng_lfsr.h
@@ -0,0 +1,152 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
+/*
+ * LRNG Linear Feedback Shift Register
+ *
+ * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+/* Status information about IRQ noise source */
+struct lrng_irq_info {
+	atomic_t num_events;	/* Number of healthy IRQs since last read */
+	atomic_t num_events_thresh;	/* Reseed threshold */
+	atomic_t reseed_in_progress;	/* Flag for on executing reseed */
+	bool irq_highres_timer;	/* Is high-resolution timer available? */
+	u32 irq_entropy_bits;	/* LRNG_IRQ_ENTROPY_BITS? */
+};
+
+/*
+ * This is the entropy pool used by the slow noise source. Its size should
+ * be at least as large as LRNG_DRNG_SECURITY_STRENGTH_BITS.
+ *
+ * The pool array is aligned to 8 bytes to comfort the kernel crypto API cipher
+ * implementations of the hash functions used to read the pool: for some
+ * accelerated implementations, we need an alignment to avoid a realignment
+ * which involves memcpy(). The alignment to 8 bytes should satisfy all crypto
+ * implementations.
+ *
+ * LRNG_POOL_SIZE is allowed to be changed only if the taps of the polynomial
+ * used for the LFSR are changed as well. The size must be in powers of 2 due
+ * to the mask handling in lrng_pool_lfsr_u32 which uses AND instead of modulo.
+ */
+struct lrng_pool {
+	union {
+		struct {
+			/*
+			 * hash_df implementation: counter, requested_bits and
+			 * pool form a linear buffer that is used in the
+			 * hash_df function specified in SP800-90A section
+			 * 10.3.1
+			 */
+			unsigned char counter;
+			__be32 requested_bits;
+
+			/* Pool */
+			atomic_t pool[LRNG_POOL_SIZE];
+			/* Ptr into pool for next IRQ word injection */
+			atomic_t pool_ptr;
+			/* rotate for LFSR */
+			atomic_t input_rotate;
+			/* All NUMA DRNGs seeded? */
+			bool all_online_numa_node_seeded;
+			/* IRQ noise source status info */
+			struct lrng_irq_info irq_info;
+			/* Serialize read of entropy pool */
+			spinlock_t lock;
+		};
+		/*
+		 * Static SHA-1 implementation in lrng_cc20_hash_buffer
+		 * processes data 64-byte-wise. Hence, ensure proper size
+		 * of LRNG entropy pool data structure.
+		 */
+		u8 hash_input_buf[LRNG_POOL_SIZE_BYTES + 64];
+	};
+};
+
+/*
+ * Implement a (modified) twisted Generalized Feedback Shift Register. (See M.
+ * Matsumoto & Y. Kurita, 1992.  Twisted GFSR generators. ACM Transactions on
+ * Modeling and Computer Simulation 2(3):179-194.  Also see M. Matsumoto & Y.
+ * Kurita, 1994.  Twisted GFSR generators II.  ACM Transactions on Modeling and
+ * Computer Simulation 4:254-266).
+ */
+static u32 const lrng_twist_table[8] = {
+	0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158,
+	0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 };
+
+/*
+ * The polynomials for the LFSR are taken from the document "Table of Linear
+ * Feedback Shift Registers" by Roy Ward, Tim Molteno, October 26, 2007.
+ * The first polynomial is from "Primitive Binary Polynomials" by Wayne
+ * Stahnke (1973) and is primitive as well as irreducible.
+ *
+ * Note, the tap values are smaller by one compared to the documentation because
+ * they are used as an index into an array where the index starts by zero.
+ *
+ * All polynomials were also checked to be primitive and irreducible with magma
+ * which ensures that the key property of the LFSR providing a compression
+ * function for entropy is guaranteed.
+ */
+static u32 const lrng_lfsr_polynomial[][4] = {
+	{ 15, 13, 12, 10 },			/* 16 words */
+	{ 31, 29, 25, 24 },			/* 32 words */
+	{ 63, 62, 60, 59 },			/* 64 words */
+	{ 127, 28, 26, 1 },			/* 128 words by Stahnke */
+	{ 255, 253, 250, 245 },			/* 256 words */
+	{ 511, 509, 506, 503 },			/* 512 words */
+	{ 1023, 1014, 1001, 1000 },		/* 1024 words */
+	{ 2047, 2034, 2033, 2028 },		/* 2048 words */
+	{ 4095, 4094, 4080, 4068 },		/* 4096 words */
+};
+
+static inline void _lrng_pool_lfsr_u32(struct lrng_pool *pool, u32 value)
+{
+	/*
+	 * Process the LFSR by altering not adjacent words but rather
+	 * more spaced apart words. Using a prime number ensures that all words
+	 * are processed evenly. As some the LFSR polynomials taps are close
+	 * together, processing adjacent words with the LSFR taps may be
+	 * inappropriate as the data just mixed-in at these taps may be not
+	 * independent from the current data to be mixed in.
+	 */
+	u32 ptr = (u32)atomic_add_return_relaxed(67, &pool->pool_ptr) &
+							(LRNG_POOL_SIZE - 1);
+	/*
+	 * Add 7 bits of rotation to the pool. At the beginning of the
+	 * pool, add an extra 7 bits rotation, so that successive passes
+	 * spread the input bits across the pool evenly.
+	 *
+	 * Note, there is a race between getting ptr and calculating
+	 * input_rotate when ptr is is obtained on two or more CPUs at the
+	 * same time. This race is irrelevant as it may only come into effect
+	 * if 3 or more CPUs race at the same time which is very unlikely. If
+	 * the race happens, it applies to one event only. As this rolling
+	 * supports the LFSR without being strictly needed, we accept this
+	 * race.
+	 */
+	u32 input_rotate = (u32)atomic_add_return_relaxed((ptr ? 7 : 14),
+					&pool->input_rotate) & 31;
+	u32 word = rol32(value, input_rotate);
+
+	BUILD_BUG_ON(LRNG_POOL_WORD_BYTES != sizeof(pool->pool[0]));
+	BUILD_BUG_ON(LRNG_POOL_SIZE - 1 !=
+		     lrng_lfsr_polynomial[CONFIG_LRNG_POOL_SIZE][0]);
+	word ^= atomic_read_u32(&pool->pool[ptr]);
+	word ^= atomic_read_u32(&pool->pool[
+		(ptr + lrng_lfsr_polynomial[CONFIG_LRNG_POOL_SIZE][0]) &
+		       (LRNG_POOL_SIZE - 1)]);
+	word ^= atomic_read_u32(&pool->pool[
+		(ptr + lrng_lfsr_polynomial[CONFIG_LRNG_POOL_SIZE][1]) &
+		       (LRNG_POOL_SIZE - 1)]);
+	word ^= atomic_read_u32(&pool->pool[
+		(ptr + lrng_lfsr_polynomial[CONFIG_LRNG_POOL_SIZE][2]) &
+		       (LRNG_POOL_SIZE - 1)]);
+	word ^= atomic_read_u32(&pool->pool[
+		(ptr + lrng_lfsr_polynomial[CONFIG_LRNG_POOL_SIZE][3]) &
+		       (LRNG_POOL_SIZE - 1)]);
+
+	word = (word >> 3) ^ lrng_twist_table[word & 7];
+	atomic_set(&pool->pool[ptr], word);
+}
+
+u32 __lrng_pool_hash_df(const struct lrng_crypto_cb *crypto_cb, void *hash,
+			struct lrng_pool *pool, u8 *outbuf, u32 requested_bits);
diff --git a/drivers/char/lrng/lrng_pool.c b/drivers/char/lrng/lrng_pool.c
new file mode 100644
index 000000000000..d1c76532a759
--- /dev/null
+++ b/drivers/char/lrng/lrng_pool.c
@@ -0,0 +1,588 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG Entropy pool management
+ *
+ * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <asm/irq_regs.h>
+#include <linux/lrng.h>
+#include <linux/percpu.h>
+#include <linux/random.h>
+#include <linux/utsname.h>
+#include <linux/workqueue.h>
+
+#include "lrng_internal.h"
+#include "lrng_lfsr.h"
+
+struct lrng_state {
+	bool lrng_operational;		/* Is DRNG operational? */
+	bool lrng_fully_seeded;		/* Is DRNG fully seeded? */
+	bool lrng_min_seeded;		/* Is DRNG minimally seeded? */
+
+	/*
+	 * To ensure that external entropy providers cannot dominate the
+	 * internal noise sources but yet cannot be dominated by internal
+	 * noise sources, the following booleans are intended to allow
+	 * external to provide seed once when a DRNG reseed occurs. This
+	 * triggering of external noise source is performed even when the
+	 * entropy pool has sufficient entropy.
+	 */
+	bool lrng_seed_hw;		/* Allow HW to provide seed */
+	bool lrng_seed_user;		/* Allow user space to provide seed */
+
+	struct work_struct lrng_seed_work;	/* (re)seed work queue */
+};
+
+static struct lrng_pool lrng_pool __aligned(LRNG_KCAPI_ALIGN) = {
+	.irq_info	= {
+		.irq_entropy_bits	= LRNG_IRQ_ENTROPY_BITS,
+		.num_events_thresh	= ATOMIC_INIT(LRNG_INIT_ENTROPY_BITS +
+						LRNG_CONDITIONING_ENTROPY_LOSS),
+		/* Sample IRQ pointer data at least during boot */
+		.irq_highres_timer	= false },
+	.lock		= __SPIN_LOCK_UNLOCKED(lrng_pool.lock)
+};
+
+static struct lrng_state lrng_state = { false, false, false, true, true };
+
+/********************************** Helper ***********************************/
+
+/* External entropy provider is allowed to provide seed data */
+bool lrng_state_exseed_allow(enum lrng_external_noise_source source)
+{
+	if (source == lrng_noise_source_hw)
+		return lrng_state.lrng_seed_hw;
+	return lrng_state.lrng_seed_user;
+}
+
+/* Enable / disable external entropy provider to furnish seed */
+void lrng_state_exseed_set(enum lrng_external_noise_source source, bool type)
+{
+	if (source == lrng_noise_source_hw)
+		lrng_state.lrng_seed_hw = type;
+	else
+		lrng_state.lrng_seed_user = type;
+}
+
+static inline void lrng_state_exseed_allow_all(void)
+{
+	lrng_state_exseed_set(lrng_noise_source_hw, true);
+	lrng_state_exseed_set(lrng_noise_source_user, true);
+}
+
+void lrng_state_init_seed_work(void)
+{
+	INIT_WORK(&lrng_state.lrng_seed_work, lrng_drng_seed_work);
+}
+
+static inline u32 lrng_entropy_to_data(u32 entropy_bits)
+{
+	return ((entropy_bits * lrng_pool.irq_info.irq_entropy_bits) /
+		LRNG_DRNG_SECURITY_STRENGTH_BITS);
+}
+
+static inline u32 lrng_data_to_entropy(u32 irqnum)
+{
+	return ((irqnum * LRNG_DRNG_SECURITY_STRENGTH_BITS) /
+		lrng_pool.irq_info.irq_entropy_bits);
+}
+
+u32 lrng_avail_entropy(void)
+{
+	return min_t(u32, LRNG_POOL_SIZE_BITS, lrng_data_to_entropy(
+			atomic_read_u32(&lrng_pool.irq_info.num_events)));
+}
+
+void lrng_set_entropy_thresh(u32 new)
+{
+	atomic_set(&lrng_pool.irq_info.num_events_thresh,
+		   lrng_entropy_to_data(new));
+}
+
+/*
+ * Reading of the LRNG pool is only allowed by one caller. The reading is
+ * only performed to (re)seed DRNGs. Thus, if this "lock" is already taken,
+ * the reseeding operation is in progress. The caller is not intended to wait
+ * but continue with its other operation.
+ */
+int lrng_pool_trylock(void)
+{
+	return atomic_cmpxchg(&lrng_pool.irq_info.reseed_in_progress, 0, 1);
+}
+
+void lrng_pool_unlock(void)
+{
+	atomic_set(&lrng_pool.irq_info.reseed_in_progress, 0);
+}
+
+void lrng_reset_state(void)
+{
+	struct lrng_irq_info *irq_info = &lrng_pool.irq_info;
+
+	atomic_set(&irq_info->num_events, 0);
+	lrng_state.lrng_operational = false;
+	lrng_state.lrng_fully_seeded = false;
+	lrng_state.lrng_min_seeded = false;
+	lrng_pool.all_online_numa_node_seeded = false;
+	pr_debug("reset LRNG\n");
+}
+
+void lrng_pool_all_numa_nodes_seeded(void)
+{
+	lrng_pool.all_online_numa_node_seeded = true;
+}
+
+bool lrng_state_min_seeded(void)
+{
+	return lrng_state.lrng_min_seeded;
+}
+
+bool lrng_state_fully_seeded(void)
+{
+	return lrng_state.lrng_fully_seeded;
+}
+
+bool lrng_state_operational(void)
+{
+	return lrng_state.lrng_operational;
+}
+
+bool lrng_pool_highres_timer(void)
+{
+	return lrng_pool.irq_info.irq_highres_timer;
+}
+
+void lrng_pool_set_entropy(u32 entropy_bits)
+{
+	atomic_set(&lrng_pool.irq_info.num_events,
+		   lrng_entropy_to_data(entropy_bits));
+}
+
+static void lrng_pool_configure(bool highres_timer, u32 irq_entropy_bits)
+{
+	struct lrng_irq_info *irq_info = &lrng_pool.irq_info;
+
+	irq_info->irq_highres_timer = highres_timer;
+	if (irq_info->irq_entropy_bits != irq_entropy_bits) {
+		irq_info->irq_entropy_bits = irq_entropy_bits;
+		/* Reset the threshold based on new oversampling factor. */
+		lrng_set_entropy_thresh(atomic_read_u32(
+						&irq_info->num_events_thresh));
+	}
+}
+
+static int __init lrng_init_time_source(void)
+{
+	if (random_get_entropy() || random_get_entropy()) {
+		/*
+		 * As the highres timer is identified here, previous interrupts
+		 * obtained during boot time are treated like a lowres-timer
+		 * would have been present.
+		 */
+		lrng_pool_configure(true, LRNG_IRQ_ENTROPY_BITS);
+	} else {
+		lrng_health_disable();
+		lrng_pool_configure(false, LRNG_IRQ_ENTROPY_BITS *
+					   LRNG_IRQ_OVERSAMPLING_FACTOR);
+		pr_warn("operating without high-resolution timer and applying "
+			"IRQ oversampling factor %u\n",
+			LRNG_IRQ_OVERSAMPLING_FACTOR);
+	}
+
+	return 0;
+}
+
+core_initcall(lrng_init_time_source);
+
+/* invoke function with buffer aligned to 4 bytes */
+void lrng_pool_lfsr(const u8 *buf, u32 buflen)
+{
+	u32 *p_buf = (u32 *)buf;
+
+	for (; buflen >= 4; buflen -= 4)
+		lrng_pool_lfsr_u32(*p_buf++);
+
+	buf = (u8 *)p_buf;
+	while (buflen--)
+		lrng_pool_lfsr_u32(*buf++);
+}
+
+void lrng_pool_lfsr_nonaligned(const u8 *buf, u32 buflen)
+{
+	while (buflen) {
+		if (!((unsigned long)buf & (sizeof(u32) - 1))) {
+			lrng_pool_lfsr(buf, buflen);
+			return;
+		}
+
+		lrng_pool_lfsr_u32(*buf++);
+		buflen--;
+	}
+}
+
+/**************************** Interrupt processing ****************************/
+
+/*
+ * Hot code path - inject data into entropy pool using LFSR
+ */
+void lrng_pool_lfsr_u32(u32 value)
+{
+	_lrng_pool_lfsr_u32(&lrng_pool, value);
+}
+
+/*
+ * Hot code path - mix data into entropy pool
+ */
+void lrng_pool_add_irq(u32 irq_num)
+{
+	struct lrng_irq_info *irq_info = &lrng_pool.irq_info;
+
+	atomic_add(irq_num, &irq_info->num_events);
+
+	/*
+	 * Once all DRNGs are fully seeded, the interrupt noise
+	 * sources will not trigger any reseeding any more.
+	 */
+	if (likely(lrng_pool.all_online_numa_node_seeded))
+		return;
+
+	/* Only try to reseed if the DRNG is alive. */
+	if (!lrng_get_available())
+		return;
+
+	/* Only trigger the DRNG reseed if we have collected enough IRQs. */
+	if (atomic_read_u32(&lrng_pool.irq_info.num_events) <
+	    atomic_read_u32(&lrng_pool.irq_info.num_events_thresh))
+		return;
+
+	/* Ensure that the seeding only occurs once at any given time. */
+	if (lrng_pool_trylock())
+		return;
+
+	/* Seed the DRNG with IRQ noise. */
+	schedule_work(&lrng_state.lrng_seed_work);
+}
+
+void lrng_pool_add_entropy(u32 entropy_bits)
+{
+	lrng_pool_add_irq(lrng_entropy_to_data(entropy_bits));
+}
+
+/*
+ * Generate a hashed output of pool using the SP800-90A section 10.3.1 hash_df
+ * function
+ */
+u32 __lrng_pool_hash_df(const struct lrng_crypto_cb *crypto_cb, void *hash,
+			struct lrng_pool *pool, u8 *outbuf, u32 requested_bits)
+{
+	u32 digestsize, requested_bytes = requested_bits >> 3,
+	    generated_bytes = 0;
+	u8 digest[64] __aligned(LRNG_KCAPI_ALIGN);
+
+	digestsize = crypto_cb->lrng_hash_digestsize(hash);
+	if (digestsize > sizeof(digest)) {
+		pr_err("Digest buffer too small\n");
+		return 0;
+	}
+
+	pool->counter = 1;
+	pool->requested_bits = cpu_to_be32(requested_bytes << 3);
+
+	while (requested_bytes) {
+		u32 tocopy = min_t(u32, requested_bytes, digestsize);
+
+		/* The counter must not wrap */
+		if (pool->counter == 0)
+			goto out;
+
+		if (crypto_cb->lrng_hash_buffer(hash, (u8 *)pool,
+						LRNG_POOL_SIZE_BYTES + 64,
+						digest))
+			goto out;
+
+		/* Copy the data out to the caller */
+		memcpy(outbuf + generated_bytes, digest, tocopy);
+		requested_bytes -= tocopy;
+		generated_bytes += tocopy;
+		pool->counter++;
+	}
+
+out:
+	/* Mix read data back into pool for backtracking resistance */
+	if (generated_bytes)
+		lrng_pool_lfsr(outbuf, generated_bytes);
+	memzero_explicit(digest, digestsize);
+	return (generated_bytes<<3);
+}
+
+static inline u32 lrng_pool_hash_df(const struct lrng_crypto_cb *crypto_cb,
+				    void *hash, u8 *outbuf, u32 requested_bits)
+{
+	return __lrng_pool_hash_df(crypto_cb, hash, &lrng_pool, outbuf,
+				   requested_bits);
+}
+
+/**
+ * lrng_get_pool() - Read the entropy pool out for use.
+ *
+ * This function handles the translation from the number of received interrupts
+ * into an entropy statement. The conversion depends on LRNG_IRQ_ENTROPY_BITS
+ * which defines how many interrupts must be received to obtain 256 bits of
+ * entropy. With this value, the function lrng_data_to_entropy converts a given
+ * data size (received interrupts, requested amount of data, etc.) into an
+ * entropy statement. lrng_entropy_to_data does the reverse.
+ *
+ * Both functions are agnostic about the type of data: when the number of
+ * interrupts is processed by these functions, the resulting entropy value is in
+ * bits as we assume the entropy of interrupts is measured in bits. When data is
+ * processed, the entropy value is in bytes as the data is measured in bytes.
+ *
+ * @outbuf: buffer to store data in with size LRNG_DRNG_SECURITY_STRENGTH_BYTES
+ * @requested_entropy_bits: requested bits of entropy -- the function will
+ *			    return at least this amount of entropy if available
+ * @entropy_retain: amount of entropy in bits that should be left in the pool
+ *
+ * Return: estimated entropy from the IRQs that was obtained
+ */
+static u32 lrng_get_pool(const struct lrng_crypto_cb *crypto_cb, void *hash,
+			 u8 *outbuf, u32 requested_entropy_bits,
+			 u32 entropy_retain)
+{
+	struct lrng_pool *pool = &lrng_pool;
+	struct lrng_state *state = &lrng_state;
+	struct lrng_irq_info *irq_info = &pool->irq_info;
+	unsigned long flags;
+
+	u32 irq_num_events_used, irq_num_events, avail_entropy_bits;
+
+	/* This get_pool operation must only be called once at a given time! */
+	spin_lock_irqsave(&pool->lock, flags);
+
+	/* How many unused interrupts are in entropy pool? */
+	irq_num_events = atomic_read_u32(&irq_info->num_events);
+	/* Convert available interrupts into entropy statement */
+	avail_entropy_bits = lrng_data_to_entropy(irq_num_events);
+
+	/* Cap available entropy to pool size */
+	avail_entropy_bits =
+			min_t(u32, avail_entropy_bits, LRNG_POOL_SIZE_BITS);
+
+	/* How much entropy we need to and can we use? */
+	if (unlikely(!state->lrng_fully_seeded)) {
+		/*
+		 * During boot time, we read 256 bits data with
+		 * avail_entropy_bits entropy. In case our conservative
+		 * entropy estimate underestimates the available entropy
+		 * we can transport as much available entropy as
+		 * possible. The entropy pool does not operate compliant to
+		 * the German AIS 21/31 NTG.1 yet.
+		 */
+		requested_entropy_bits =
+				LRNG_DRNG_SECURITY_STRENGTH_BITS;
+	} else {
+		/* Provide all entropy above retaining level */
+		if (avail_entropy_bits < entropy_retain) {
+			requested_entropy_bits = 0;
+			goto out;
+		}
+		avail_entropy_bits -= entropy_retain;
+		requested_entropy_bits = min_t(u32, avail_entropy_bits,
+					       requested_entropy_bits);
+	}
+
+	/* Hash is a compression function: we generate entropy amount of data */
+	requested_entropy_bits = round_down(requested_entropy_bits, 8);
+
+	requested_entropy_bits = lrng_pool_hash_df(crypto_cb, hash, outbuf,
+						   requested_entropy_bits);
+
+	/* Boot time: After getting the full buffer adjust the entropy value. */
+	requested_entropy_bits = min_t(u32, avail_entropy_bits,
+				       requested_entropy_bits);
+
+out:
+	/* Convert used entropy into interrupt number for subtraction */
+	irq_num_events_used = lrng_entropy_to_data(requested_entropy_bits);
+
+	/*
+	 * The hash_df operation entropy assessment shows that the output
+	 * entropy is one bit smaller than the input entropy. Therefore we
+	 * account for this one bit of entropy here: if we have sufficient
+	 * entropy in the LFSR, we say we used one bit of entropy more.
+	 * Otherwise we reduce the amount of entropy we say we generated with
+	 * the hash_df.
+	 */
+	if (irq_num_events_used) {
+		if ((irq_num_events_used + LRNG_CONDITIONING_ENTROPY_LOSS) <=
+		    lrng_entropy_to_data(avail_entropy_bits)) {
+			irq_num_events_used += LRNG_CONDITIONING_ENTROPY_LOSS;
+		} else {
+			if (unlikely(requested_entropy_bits <
+				     LRNG_CONDITIONING_ENTROPY_LOSS))
+				requested_entropy_bits = 0;
+			else
+				requested_entropy_bits -=
+						LRNG_CONDITIONING_ENTROPY_LOSS;
+		}
+	}
+
+	/*
+	 * New events might have arrived in the meanwhile and we don't
+	 * want to throw them away unconditionally. On the other hand,
+	 * these new events might have been mixed in before
+	 * lrng_hash_df_pool() had been able to draw any entropy
+	 * from the pool and thus, the pool capacity might have been
+	 * exceeded at some point. Note that in theory, some events
+	 * might get lost inbetween the atomic_read() and
+	 * atomic_set() below. But that's fine, because it's no real
+	 * concern while code preventing this would come at the cost of
+	 * additional complexity. Likewise, some events which arrived
+	 * after full or partial completion of the __lrng_hash_df_pool()
+	 * above might get unnecessarily thrown away by the min()
+	 * operation below; the same argument applies there.
+	 */
+	irq_num_events = atomic_read_u32(&irq_info->num_events);
+	irq_num_events = min_t(u32, irq_num_events,
+			       lrng_entropy_to_data(LRNG_POOL_SIZE_BITS));
+	irq_num_events -= irq_num_events_used;
+	atomic_set(&irq_info->num_events, irq_num_events);
+
+	spin_unlock_irqrestore(&pool->lock, flags);
+
+	/* Obtain entropy statement in bits from the used entropy */
+	pr_debug("obtained %u bits of entropy from %u newly collected "
+		 "interrupts - not using %u interrupts\n",
+		 requested_entropy_bits, irq_num_events_used,
+		 irq_num_events);
+
+	return requested_entropy_bits;
+}
+
+/* Fill the seed buffer with data from the noise sources */
+int lrng_fill_seed_buffer(const struct lrng_crypto_cb *crypto_cb, void *hash,
+			  struct entropy_buf *entropy_buf, u32 entropy_retain)
+{
+	struct lrng_state *state = &lrng_state;
+	u32 total_entropy_bits = 0;
+
+	/* Require at least 128 bits of entropy for any reseed. */
+	if (state->lrng_fully_seeded &&
+	    (lrng_avail_entropy() <
+	     lrng_slow_noise_req_entropy(LRNG_MIN_SEED_ENTROPY_BITS +
+					 LRNG_CONDITIONING_ENTROPY_LOSS) +
+	      entropy_retain))
+		goto wakeup;
+
+	/*
+	 * Concatenate the output of the noise sources. This would be the
+	 * spot to add an entropy extractor logic if desired. Note, this
+	 * has the ability to collect entropy equal or larger than the DRNG
+	 * strength.
+	 */
+	total_entropy_bits = lrng_get_pool(crypto_cb, hash, entropy_buf->a,
+					   LRNG_DRNG_SECURITY_STRENGTH_BITS,
+					   entropy_retain);
+	total_entropy_bits += lrng_get_arch(entropy_buf->b);
+	total_entropy_bits += lrng_get_jent(entropy_buf->c,
+					    LRNG_DRNG_SECURITY_STRENGTH_BYTES);
+
+	/* also reseed the DRNG with the current time stamp */
+	entropy_buf->now = random_get_entropy();
+
+	/* allow external entropy provider to provide seed */
+	lrng_state_exseed_allow_all();
+
+wakeup:
+	/*
+	 * Shall we wake up user space writers? This location covers
+	 * ensures that the user space provider does not dominate the internal
+	 * noise sources since in case the first call of this function finds
+	 * sufficient entropy in the entropy pool, it will not trigger the
+	 * wakeup. This implies that when the next /dev/urandom read happens,
+	 * the entropy pool is drained.
+	 */
+	lrng_writer_wakeup();
+
+	return total_entropy_bits;
+}
+
+/**
+ * lrng_init_ops() - Set seed stages of LRNG
+ *
+ * Set the slow noise source reseed trigger threshold. The initial threshold
+ * is set to the minimum data size that can be read from the pool: a word. Upon
+ * reaching this value, the next seed threshold of 128 bits is set followed
+ * by 256 bits.
+ *
+ * @entropy_bits: size of entropy currently injected into DRNG
+ */
+void lrng_init_ops(u32 seed_bits)
+{
+	struct lrng_state *state = &lrng_state;
+
+	if (state->lrng_operational)
+		return;
+
+	/* DRNG is seeded with full security strength */
+	if (state->lrng_fully_seeded) {
+		state->lrng_operational = lrng_sp80090b_startup_complete();
+		lrng_process_ready_list();
+		lrng_init_wakeup();
+	} else if (seed_bits >= LRNG_FULL_SEED_ENTROPY_BITS) {
+		invalidate_batched_entropy();
+		state->lrng_fully_seeded = true;
+		state->lrng_operational = lrng_sp80090b_startup_complete();
+		state->lrng_min_seeded = true;
+		pr_info("LRNG fully seeded with %u bits of entropy\n",
+			seed_bits);
+		lrng_set_entropy_thresh(LRNG_FULL_SEED_ENTROPY_BITS +
+					LRNG_CONDITIONING_ENTROPY_LOSS);
+		lrng_process_ready_list();
+		lrng_init_wakeup();
+
+	} else if (!state->lrng_min_seeded) {
+
+		/* DRNG is seeded with at least 128 bits of entropy */
+		if (seed_bits >= LRNG_MIN_SEED_ENTROPY_BITS) {
+			invalidate_batched_entropy();
+			state->lrng_min_seeded = true;
+			pr_info("LRNG minimally seeded with %u bits of "
+				"entropy\n", seed_bits);
+			lrng_set_entropy_thresh(
+				lrng_slow_noise_req_entropy(
+					LRNG_FULL_SEED_ENTROPY_BITS +
+					LRNG_CONDITIONING_ENTROPY_LOSS));
+			lrng_process_ready_list();
+			lrng_init_wakeup();
+
+		/* DRNG is seeded with at least LRNG_INIT_ENTROPY_BITS bits */
+		} else if (seed_bits >= LRNG_INIT_ENTROPY_BITS) {
+			pr_info("LRNG initial entropy level %u bits of "
+				"entropy\n", seed_bits);
+			lrng_set_entropy_thresh(
+				lrng_slow_noise_req_entropy(
+					LRNG_MIN_SEED_ENTROPY_BITS +
+					LRNG_CONDITIONING_ENTROPY_LOSS));
+		}
+	}
+}
+
+int __init rand_initialize(void)
+{
+	ktime_t now_time = ktime_get_real();
+	unsigned int i, rand;
+
+	lrng_pool_lfsr_u32(now_time);
+	for (i = 0; i < LRNG_POOL_SIZE; i++) {
+		if (!arch_get_random_seed_int(&rand) &&
+		    !arch_get_random_int(&rand))
+			rand = random_get_entropy();
+		lrng_pool_lfsr_u32(rand);
+	}
+	lrng_pool_lfsr_nonaligned((u8 *)utsname(), sizeof(*(utsname())));
+
+	return 0;
+}
diff --git a/drivers/char/lrng/lrng_sw_noise.c b/drivers/char/lrng/lrng_sw_noise.c
new file mode 100644
index 000000000000..c21db23875fc
--- /dev/null
+++ b/drivers/char/lrng/lrng_sw_noise.c
@@ -0,0 +1,102 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG Slow Noise Source: Interrupt data collection
+ *
+ * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#include <asm/irq_regs.h>
+#include <asm/ptrace.h>
+#include <linux/random.h>
+
+#include "lrng_internal.h"
+#include "lrng_sw_noise.h"
+
+/* Holder of time stamps before mixing them into the entropy pool */
+static DEFINE_PER_CPU(u32 [LRNG_TIME_ARRAY_SIZE], lrng_time);
+static DEFINE_PER_CPU(u32, lrng_time_ptr) = 0;
+static DEFINE_PER_CPU(u8, lrng_time_irqs) = 0;
+
+/*
+ * Batching up of entropy in per-CPU array before injecting into entropy pool.
+ */
+static inline void lrng_time_process(void)
+{
+	u32 i, ptr, now_time = random_get_entropy() &
+			       (likely(lrng_state_fully_seeded()) ?
+				LRNG_TIME_SLOTSIZE_MASK : (u32)-1);
+	enum lrng_health_res health_test;
+
+	/* Ensure sufficient space in lrng_time_irqs */
+	BUILD_BUG_ON(LRNG_TIME_NUM_VALUES >= (1 << (sizeof(u8) << 3)));
+	BUILD_BUG_ON(LRNG_TIME_ARRAY_MEMBER_BITS % LRNG_TIME_SLOTSIZE_BITS);
+	/* Ensure consistency of values */
+	BUILD_BUG_ON(LRNG_TIME_ARRAY_MEMBER_BITS != sizeof(lrng_time[0]) << 3);
+
+	if (lrng_raw_entropy_store(now_time))
+		return;
+
+	health_test = lrng_health_test(now_time);
+	if (health_test > lrng_health_fail_use)
+		return;
+
+	/* During boot time, we mix the full time stamp directly into LFSR */
+	if (unlikely(!lrng_state_fully_seeded())) {
+		lrng_pool_lfsr_u32(now_time);
+		if (health_test == lrng_health_pass)
+			lrng_pool_add_irq(1);
+		return;
+	}
+
+	ptr = this_cpu_inc_return(lrng_time_ptr) & LRNG_TIME_WORD_MASK;
+	this_cpu_or(lrng_time[lrng_time_idx2array(ptr)],
+		    lrng_time_slot_val(now_time & LRNG_TIME_SLOTSIZE_MASK,
+				       lrng_time_idx2slot(ptr)));
+
+	/* Interrupt delivers entropy if health test passes */
+	if (health_test == lrng_health_pass)
+		this_cpu_inc(lrng_time_irqs);
+
+	/* Only mix the buffer of time stamps into LFSR when wrapping */
+	if (ptr < LRNG_TIME_WORD_MASK)
+		return;
+
+	for (i = 0; i < LRNG_TIME_ARRAY_SIZE; i++) {
+		lrng_pool_lfsr_u32(this_cpu_read(lrng_time[i]));
+		this_cpu_write(lrng_time[i], 0);
+	}
+	lrng_pool_add_irq(this_cpu_read(lrng_time_irqs));
+	this_cpu_write(lrng_time_irqs, 0);
+}
+
+/*
+ * Hot code path - Callback for interrupt handler
+ */
+void add_interrupt_randomness(int irq, int irq_flags)
+{
+	lrng_time_process();
+
+	if (!lrng_pool_highres_timer()) {
+		struct pt_regs *regs = get_irq_regs();
+		static atomic_t reg_idx = ATOMIC_INIT(0);
+		u64 ip;
+
+		lrng_pool_lfsr_u32(jiffies);
+		lrng_pool_lfsr_u32(irq);
+		lrng_pool_lfsr_u32(irq_flags);
+
+		if (regs) {
+			u32 *ptr = (u32 *)regs;
+			int reg_ptr = atomic_add_return_relaxed(1, &reg_idx);
+			size_t n = (sizeof(struct pt_regs) / sizeof(u32));
+
+			ip = instruction_pointer(regs);
+			lrng_pool_lfsr_u32(*(ptr + (reg_ptr % n)));
+		} else
+			ip = _RET_IP_;
+
+		lrng_pool_lfsr_u32(ip >> 32);
+		lrng_pool_lfsr_u32(ip);
+	}
+}
+EXPORT_SYMBOL(add_interrupt_randomness);
diff --git a/drivers/char/lrng/lrng_sw_noise.h b/drivers/char/lrng/lrng_sw_noise.h
new file mode 100644
index 000000000000..107c6f9153bc
--- /dev/null
+++ b/drivers/char/lrng/lrng_sw_noise.h
@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
+/*
+ * LRNG Slow Noise Source: Time stamp array handling
+ *
+ * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+/*
+ * To limit the impact on the interrupt handling, the LRNG concatenates
+ * entropic LSB parts of the time stamps in a per-CPU array and only
+ * injects them into the entropy pool when the array is full.
+ */
+
+/* Store multiple integers in one u32 */
+#define LRNG_TIME_SLOTSIZE_BITS		(8)
+#define LRNG_TIME_SLOTSIZE_MASK		((1 << LRNG_TIME_SLOTSIZE_BITS) - 1)
+#define LRNG_TIME_ARRAY_MEMBER_BITS	(4 << 3)
+#define LRNG_TIME_SLOTS_PER_UINT	(LRNG_TIME_ARRAY_MEMBER_BITS / \
+					 LRNG_TIME_SLOTSIZE_BITS)
+
+/*
+ * Number of time values to store in the array - in small environments
+ * only one atomic_t variable per CPU is used.
+ */
+#define LRNG_TIME_NUM_VALUES		(CONFIG_BASE_SMALL ?		\
+					 LRNG_TIME_SLOTS_PER_UINT : 64)
+/* Mask of LSB of time stamp to store */
+#define LRNG_TIME_WORD_MASK		(LRNG_TIME_NUM_VALUES - 1)
+
+#define LRNG_TIME_SLOTS_MASK		(LRNG_TIME_SLOTS_PER_UINT - 1)
+#define LRNG_TIME_ARRAY_SIZE		(LRNG_TIME_NUM_VALUES /	\
+					 LRNG_TIME_SLOTS_PER_UINT)
+
+/* Starting bit index of slot */
+static inline unsigned int lrng_time_slot2bitindex(unsigned int slot)
+{
+	return (LRNG_TIME_SLOTSIZE_BITS * slot);
+}
+
+/* Convert index into the array index */
+static inline unsigned int lrng_time_idx2array(unsigned int idx)
+{
+	return idx / LRNG_TIME_SLOTS_PER_UINT;
+}
+
+/* Convert index into the slot of a given array index */
+static inline unsigned int lrng_time_idx2slot(unsigned int idx)
+{
+	return idx & LRNG_TIME_SLOTS_MASK;
+}
+
+/* Convert value into slot value */
+static inline unsigned int lrng_time_slot_val(unsigned int val,
+					      unsigned int slot)
+{
+	return val << lrng_time_slot2bitindex(slot);
+}
diff --git a/include/linux/lrng.h b/include/linux/lrng.h
new file mode 100644
index 000000000000..2c3d2ed32a91
--- /dev/null
+++ b/include/linux/lrng.h
@@ -0,0 +1,63 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
+/*
+ * Copyright (C) 2018 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#ifndef _LRNG_H
+#define _LRNG_H
+
+#include <linux/errno.h>
+#include <linux/types.h>
+
+/**
+ * struct lrng_crypto_cb - cryptographic callback functions
+ * @lrng_drng_name		Name of DRNG
+ * @lrng_hash_name		Name of Hash used for reading entropy pool
+ * @lrng_drng_alloc:		Allocate DRNG -- the provided integer should be
+ *				used for sanity checks.
+ *				return: allocated data structure or PTR_ERR on
+ *					error
+ * @lrng_drng_dealloc:		Deallocate DRNG
+ * @lrng_drng_seed_helper:	Seed the DRNG with data of arbitrary length
+ *				drng: is pointer to data structure allocated
+ *				      with lrng_drng_alloc
+ *				return: >= 0 on success, < 0 on error
+ * @lrng_drng_generate_helper:	Generate random numbers from the DRNG with
+ *				arbitrary length
+ * @lrng_hash_alloc:		Allocate the hash for reading the entropy pool
+ *				return: allocated data structure (NULL is
+ *					success too) or ERR_PTR on error
+ * @lrng_hash_dealloc:		Deallocate Hash
+ * @lrng_hash_digestsize:	Return the digestsize for the used hash to read
+ *				out entropy pool
+ *				hash: is pointer to data structure allocated
+ *				      with lrng_hash_alloc
+ *				return: size of digest of hash in bytes
+ * @lrng_hash_buffer:		Generate hash
+ *				hash: is pointer to data structure allocated
+ *				      with lrng_hash_alloc
+ *				return: 0 on success, < 0 on error
+ */
+struct lrng_crypto_cb {
+	const char *(*lrng_drng_name)(void);
+	const char *(*lrng_hash_name)(void);
+	void *(*lrng_drng_alloc)(u32 sec_strength);
+	void (*lrng_drng_dealloc)(void *drng);
+	int (*lrng_drng_seed_helper)(void *drng, const u8 *inbuf, u32 inbuflen);
+	int (*lrng_drng_generate_helper)(void *drng, u8 *outbuf, u32 outbuflen);
+	void *(*lrng_hash_alloc)(const u8 *key, u32 keylen);
+	void (*lrng_hash_dealloc)(void *hash);
+	u32 (*lrng_hash_digestsize)(void *hash);
+	int (*lrng_hash_buffer)(void *hash, const u8 *inbuf, u32 inbuflen,
+				u8 *digest);
+};
+
+/* Register cryptographic backend */
+#ifdef CONFIG_LRNG_DRNG_SWITCH
+int lrng_set_drng_cb(const struct lrng_crypto_cb *cb);
+#else	/* CONFIG_LRNG_DRNG_SWITCH */
+static inline int
+lrng_set_drng_cb(const struct lrng_crypto_cb *cb) { return -EOPNOTSUPP; }
+#endif	/* CONFIG_LRNG_DRNG_SWITCH */
+
+#endif /* _LRNG_H */
-- 
2.24.1





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v28 02/12] LRNG - allocate one DRNG instance per NUMA node
  2020-01-15 10:31       ` [PATCH v28 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
  2020-01-15 10:31         ` [PATCH v28 01/12] Linux Random Number Generator Stephan Müller
@ 2020-01-15 10:32         ` Stephan Müller
  2020-01-15 10:32         ` [PATCH v28 03/12] LRNG - sysctls and /proc interface Stephan Müller
                           ` (10 subsequent siblings)
  12 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2020-01-15 10:32 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap, Julia Lawall, Dan Carpenter

In order to improve NUMA-locality when serving getrandom(2) requests,
allocate one DRNG instance per node.

The DRNG instance that is present right from the start of the kernel is
reused as the first per-NUMA-node DRNG. For all remaining online NUMA
nodes a new DRNG instance is allocated.

During boot time, the multiple DRNG instances are seeded sequentially.
With this, the first DRNG instance (referenced as the initial DRNG
in the code) is completely seeded with 256 bits of entropy before the
next DRNG instance is completely seeded.

When random numbers are requested, the NUMA-node-local DRNG is checked
whether it has been already fully seeded. If this is not the case, the
initial DRNG is used to serve the request.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Makefile        |   2 +
 drivers/char/lrng/lrng_internal.h |   5 ++
 drivers/char/lrng/lrng_numa.c     | 101 ++++++++++++++++++++++++++++++
 3 files changed, 108 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_numa.c

diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index 1d2a0211973d..0a32f22c2c1a 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -7,3 +7,5 @@ obj-y				+= lrng_pool.o lrng_aux.o \
 				   lrng_sw_noise.o lrng_archrandom.o \
 				   lrng_drng.o lrng_chacha20.o \
 				   lrng_interfaces.o \
+
+obj-$(CONFIG_NUMA)		+= lrng_numa.o
diff --git a/drivers/char/lrng/lrng_internal.h b/drivers/char/lrng/lrng_internal.h
index edf38121ec65..ecb0a7ad5e7e 100644
--- a/drivers/char/lrng/lrng_internal.h
+++ b/drivers/char/lrng/lrng_internal.h
@@ -246,8 +246,13 @@ int lrng_drng_get_sleep(u8 *outbuf, u32 outbuflen);
 void lrng_drng_force_reseed(void);
 void lrng_drng_seed_work(struct work_struct *dummy);
 
+#ifdef CONFIG_NUMA
+struct lrng_drng **lrng_drng_instances(void);
+void lrng_drngs_numa_alloc(void);
+#else	/* CONFIG_NUMA */
 static inline struct lrng_drng **lrng_drng_instances(void) { return NULL; }
 static inline void lrng_drngs_numa_alloc(void) { return; }
+#endif /* CONFIG_NUMA */
 
 /************************** Health Test linking code **************************/
 
diff --git a/drivers/char/lrng/lrng_numa.c b/drivers/char/lrng/lrng_numa.c
new file mode 100644
index 000000000000..947c5b3ed517
--- /dev/null
+++ b/drivers/char/lrng/lrng_numa.c
@@ -0,0 +1,101 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG NUMA support
+ *
+ * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/lrng.h>
+#include <linux/slab.h>
+
+#include "lrng_internal.h"
+
+static struct lrng_drng **lrng_drng __read_mostly = NULL;
+
+struct lrng_drng **lrng_drng_instances(void)
+{
+	return lrng_drng;
+}
+
+/* Allocate the data structures for the per-NUMA node DRNGs */
+static void _lrng_drngs_numa_alloc(struct work_struct *work)
+{
+	struct lrng_drng **drngs;
+	struct lrng_drng *lrng_drng_init = lrng_drng_init_instance();
+	u32 node;
+	bool init_drng_used = false;
+
+	mutex_lock(&lrng_crypto_cb_update);
+
+	/* per-NUMA-node DRNGs are already present */
+	if (lrng_drng)
+		goto unlock;
+
+	drngs = kcalloc(nr_node_ids, sizeof(void *), GFP_KERNEL|__GFP_NOFAIL);
+	for_each_online_node(node) {
+		struct lrng_drng *drng;
+
+		if (!init_drng_used) {
+			drngs[node] = lrng_drng_init;
+			init_drng_used = true;
+			continue;
+		}
+
+		drng = kmalloc_node(sizeof(struct lrng_drng),
+				     GFP_KERNEL|__GFP_NOFAIL, node);
+		memset(drng, 0, sizeof(lrng_drng));
+
+		drng->crypto_cb = lrng_drng_init->crypto_cb;
+		drng->drng = drng->crypto_cb->lrng_drng_alloc(
+					LRNG_DRNG_SECURITY_STRENGTH_BYTES);
+		if (IS_ERR(drng->drng)) {
+			kfree(drng);
+			goto err;
+		}
+
+		mutex_init(&drng->lock);
+		spin_lock_init(&drng->spin_lock);
+
+		/*
+		 * No reseeding of NUMA DRNGs from previous DRNGs as this
+		 * would complicate the code. Let it simply reseed.
+		 */
+		lrng_drng_reset(drng);
+		drngs[node] = drng;
+
+		lrng_pool_inc_numa_node();
+		pr_info("DRNG for NUMA node %d allocated\n", node);
+	}
+
+	/* Ensure that all NUMA nodes receive changed memory here. */
+	mb();
+
+	if (!cmpxchg(&lrng_drng, NULL, drngs))
+		goto unlock;
+
+err:
+	for_each_online_node(node) {
+		struct lrng_drng *drng = drngs[node];
+
+		if (drng == lrng_drng_init)
+			continue;
+
+		if (drng) {
+			drng->crypto_cb->lrng_drng_dealloc(drng->drng);
+			kfree(drng);
+		}
+	}
+	kfree(drngs);
+
+unlock:
+	mutex_unlock(&lrng_crypto_cb_update);
+}
+
+static DECLARE_WORK(lrng_drngs_numa_alloc_work, _lrng_drngs_numa_alloc);
+
+void lrng_drngs_numa_alloc(void)
+{
+	schedule_work(&lrng_drngs_numa_alloc_work);
+}
-- 
2.24.1





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v28 03/12] LRNG - sysctls and /proc interface
  2020-01-15 10:31       ` [PATCH v28 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
  2020-01-15 10:31         ` [PATCH v28 01/12] Linux Random Number Generator Stephan Müller
  2020-01-15 10:32         ` [PATCH v28 02/12] LRNG - allocate one DRNG instance per NUMA node Stephan Müller
@ 2020-01-15 10:32         ` Stephan Müller
  2020-01-15 10:32         ` [PATCH v28 04/12] LRNG - add switchable DRNG support Stephan Müller
                           ` (9 subsequent siblings)
  12 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2020-01-15 10:32 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap, Julia Lawall, Dan Carpenter

The LRNG sysctl interface provides the same controls as the existing
/dev/random implementation. These sysctls behave identically and are
implemented identically. The goal is to allow a possible merge of the
existing /dev/random implementation with this implementation which
implies that this patch tries have a very close similarity. Yet, all
sysctls are documented at [1].

In addition, it provides the file lrng_type which provides details about
the LRNG:

- the name of the DRNG that produces the random numbers for /dev/random,
/dev/urandom, getrandom(2)

- the hash used to produce random numbers from the entropy pool

- the number of secondary DRNG instances

- indicator whether the LRNG operates SP800-90B compliant

- indicator whether a high-resolution timer is identified - only with a
high-resolution timer the interrupt noise source will deliver sufficient
entropy

- indicator whether the LRNG has been minimally seeded (i.e. is the
secondary DRNG seeded with at least 128 bits of of entropy)

- indicator whether the LRNG has been fully seeded (i.e. is the
secondary DRNG seeded with at least 256 bits of entropy)

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

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Makefile          |   1 +
 drivers/char/lrng/lrng_interfaces.c |   1 -
 drivers/char/lrng/lrng_internal.h   |   4 +
 drivers/char/lrng/lrng_proc.c       | 163 ++++++++++++++++++++++++++++
 4 files changed, 168 insertions(+), 1 deletion(-)
 create mode 100644 drivers/char/lrng/lrng_proc.c

diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index 0a32f22c2c1a..e69c176f0161 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -9,3 +9,4 @@ obj-y				+= lrng_pool.o lrng_aux.o \
 				   lrng_interfaces.o \
 
 obj-$(CONFIG_NUMA)		+= lrng_numa.o
+obj-$(CONFIG_SYSCTL)		+= lrng_proc.o
diff --git a/drivers/char/lrng/lrng_interfaces.c b/drivers/char/lrng/lrng_interfaces.c
index d6ddc72fc9b7..8e96c3ade76e 100644
--- a/drivers/char/lrng/lrng_interfaces.c
+++ b/drivers/char/lrng/lrng_interfaces.c
@@ -34,7 +34,6 @@ static DECLARE_WAIT_QUEUE_HEAD(lrng_write_wait);
 static DECLARE_WAIT_QUEUE_HEAD(lrng_init_wait);
 static struct fasync_struct *fasync;
 
-struct ctl_table random_table[];
 /********************************** Helper ***********************************/
 
 /* Is the DRNG seed level too low? */
diff --git a/drivers/char/lrng/lrng_internal.h b/drivers/char/lrng/lrng_internal.h
index ecb0a7ad5e7e..f65fc6647e8a 100644
--- a/drivers/char/lrng/lrng_internal.h
+++ b/drivers/char/lrng/lrng_internal.h
@@ -116,7 +116,11 @@ void lrng_cc20_init_state(struct chacha20_state *state);
 
 /********************************** /proc *************************************/
 
+#ifdef CONFIG_SYSCTL
+void lrng_pool_inc_numa_node(void);
+#else
 static inline void lrng_pool_inc_numa_node(void) { }
+#endif
 
 /****************************** LRNG interfaces *******************************/
 
diff --git a/drivers/char/lrng/lrng_proc.c b/drivers/char/lrng/lrng_proc.c
new file mode 100644
index 000000000000..f4ee01f61925
--- /dev/null
+++ b/drivers/char/lrng/lrng_proc.c
@@ -0,0 +1,163 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG proc and sysctl interfaces
+ *
+ * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#include <linux/lrng.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/sysctl.h>
+#include <linux/uuid.h>
+
+#include "lrng_internal.h"
+
+/*
+ * This function is used to return both the bootid UUID, and random
+ * UUID.  The difference is in whether table->data is NULL; if it is,
+ * then a new UUID is generated and returned to the user.
+ *
+ * If the user accesses this via the proc interface, the UUID will be
+ * returned as an ASCII string in the standard UUID format; if via the
+ * sysctl system call, as 16 bytes of binary data.
+ */
+static int lrng_proc_do_uuid(struct ctl_table *table, int write,
+			     void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	struct ctl_table fake_table;
+	unsigned char buf[64], tmp_uuid[16], *uuid;
+
+	uuid = table->data;
+	if (!uuid) {
+		uuid = tmp_uuid;
+		generate_random_uuid(uuid);
+	} else {
+		static DEFINE_SPINLOCK(bootid_spinlock);
+
+		spin_lock(&bootid_spinlock);
+		if (!uuid[8])
+			generate_random_uuid(uuid);
+		spin_unlock(&bootid_spinlock);
+	}
+
+	sprintf(buf, "%pU", uuid);
+
+	fake_table.data = buf;
+	fake_table.maxlen = sizeof(buf);
+
+	return proc_dostring(&fake_table, write, buffer, lenp, ppos);
+}
+
+static int lrng_proc_do_entropy(struct ctl_table *table, int write,
+				void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	struct ctl_table fake_table;
+	int entropy_count;
+
+	entropy_count = lrng_avail_entropy();
+
+	fake_table.data = &entropy_count;
+	fake_table.maxlen = sizeof(entropy_count);
+
+	return proc_dointvec(&fake_table, write, buffer, lenp, ppos);
+}
+
+static int lrng_sysctl_poolsize = LRNG_POOL_SIZE_BITS;
+static int lrng_min_write_thresh;
+static int lrng_max_write_thresh = LRNG_POOL_SIZE_BITS;
+static char lrng_sysctl_bootid[16];
+static int lrng_drng_reseed_max_min;
+
+struct ctl_table random_table[] = {
+	{
+		.procname	= "poolsize",
+		.data		= &lrng_sysctl_poolsize,
+		.maxlen		= sizeof(int),
+		.mode		= 0444,
+		.proc_handler	= proc_dointvec,
+	},
+	{
+		.procname	= "entropy_avail",
+		.maxlen		= sizeof(int),
+		.mode		= 0444,
+		.proc_handler	= lrng_proc_do_entropy,
+	},
+	{
+		.procname	= "write_wakeup_threshold",
+		.data		= &lrng_write_wakeup_bits,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec_minmax,
+		.extra1		= &lrng_min_write_thresh,
+		.extra2		= &lrng_max_write_thresh,
+	},
+	{
+		.procname	= "boot_id",
+		.data		= &lrng_sysctl_bootid,
+		.maxlen		= 16,
+		.mode		= 0444,
+		.proc_handler	= lrng_proc_do_uuid,
+	},
+	{
+		.procname	= "uuid",
+		.maxlen		= 16,
+		.mode		= 0444,
+		.proc_handler	= lrng_proc_do_uuid,
+	},
+	{
+		.procname       = "urandom_min_reseed_secs",
+		.data           = &lrng_drng_reseed_max_time,
+		.maxlen         = sizeof(int),
+		.mode           = 0644,
+		.proc_handler   = proc_dointvec,
+		.extra1		= &lrng_drng_reseed_max_min,
+	},
+	{ }
+};
+
+/* Number of online DRNGs */
+static u32 numa_drngs = 1;
+
+void lrng_pool_inc_numa_node(void)
+{
+	numa_drngs++;
+}
+
+static int lrng_proc_type_show(struct seq_file *m, void *v)
+{
+	struct lrng_drng *lrng_drng_init = lrng_drng_init_instance();
+	unsigned long flags = 0;
+	unsigned char buf[300];
+
+	lrng_drng_lock(lrng_drng_init, &flags);
+	snprintf(buf, sizeof(buf),
+		 "DRNG name: %s\n"
+		 "Hash for reading entropy pool: %s\n"
+		 "DRNG security strength: %d bits\n"
+		 "number of DRNG instances: %u\n"
+		 "SP800-90B compliance: %s\n"
+		 "High-resolution timer: %s\n"
+		 "LRNG minimally seeded: %s\n"
+		 "LRNG fully seeded: %s\n",
+		 lrng_drng_init->crypto_cb->lrng_drng_name(),
+		 lrng_drng_init->crypto_cb->lrng_hash_name(),
+		 LRNG_DRNG_SECURITY_STRENGTH_BITS, numa_drngs,
+		 lrng_sp80090b_compliant() ? "true" : "false",
+		 lrng_pool_highres_timer() ? "true" : "false",
+		 lrng_state_min_seeded() ? "true" : "false",
+		 lrng_state_fully_seeded() ? "true" : "false");
+	lrng_drng_unlock(lrng_drng_init, &flags);
+
+	seq_write(m, buf, strlen(buf));
+
+	return 0;
+}
+
+static int __init lrng_proc_type_init(void)
+{
+	proc_create_single("lrng_type", 0444, NULL, &lrng_proc_type_show);
+	return 0;
+}
+
+module_init(lrng_proc_type_init);
-- 
2.24.1





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v28 04/12] LRNG - add switchable DRNG support
  2020-01-15 10:31       ` [PATCH v28 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                           ` (2 preceding siblings ...)
  2020-01-15 10:32         ` [PATCH v28 03/12] LRNG - sysctls and /proc interface Stephan Müller
@ 2020-01-15 10:32         ` Stephan Müller
  2020-01-15 10:33         ` [PATCH v28 05/12] crypto: DRBG - externalize DRBG functions for LRNG Stephan Müller
                           ` (8 subsequent siblings)
  12 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2020-01-15 10:32 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap, Julia Lawall, Dan Carpenter

The DRNG switch support allows replacing the DRNG mechanism of the
LRNG. The switching support rests on the interface definition of
include/linux/lrng.h. A new DRNG is implemented by filling in the
interface defined in this header file.

In addition to the DRNG, the extension also has to provide a hash
implementation that is used to hash the entropy pool for random number
extraction.

Note: It is permissible to implement a DRNG whose operations may sleep.
However, the hash function must not sleep.

The switchable DRNG support allows replacing the DRNG at runtime.
However, only one DRNG extension is allowed to be loaded at any given
time. Before replacing it with another DRNG implementation, the possibly
existing DRNG extension must be unloaded.

The switchable DRNG extension activates the new DRNG during load time.
It is expected, however, that such a DRNG switch would be done only once
by an administrator to load the intended DRNG implementation.

It is permissible to compile DRNG extensions either as kernel modules or
statically. The initialization of the DRNG extension should be performed
with a late_initcall to ensure the extension is available when user
space starts but after all other initialization completed.
The initialization is performed by registering the function call data
structure with the lrng_set_drng_cb function. In order to unload the
DRNG extension, lrng_set_drng_cb must be invoked with the NULL
parameter.

The DRNG extension should always provide a security strength that is at
least as strong as LRNG_DRNG_SECURITY_STRENGTH_BITS.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Kconfig       |   7 ++
 drivers/char/lrng/Makefile      |   1 +
 drivers/char/lrng/lrng_switch.c | 183 ++++++++++++++++++++++++++++++++
 3 files changed, 191 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_switch.c

diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
index 56f13efd3592..cb701bb0b8b6 100644
--- a/drivers/char/lrng/Kconfig
+++ b/drivers/char/lrng/Kconfig
@@ -64,4 +64,11 @@ config LRNG_POOL_SIZE
 	default 7 if LRNG_POOL_SIZE_65536
 	default 8 if LRNG_POOL_SIZE_131072
 
+menuconfig LRNG_DRNG_SWITCH
+	bool "Support DRNG runtime switching"
+	help
+	  The Linux RNG per default uses a ChaCha20 DRNG that is
+	  accessible via the external interfaces. With this configuration
+	  option other DRNGs can be selected and loaded at runtime.
+
 endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index e69c176f0161..31cfe87c999e 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -10,3 +10,4 @@ obj-y				+= lrng_pool.o lrng_aux.o \
 
 obj-$(CONFIG_NUMA)		+= lrng_numa.o
 obj-$(CONFIG_SYSCTL)		+= lrng_proc.o
+obj-$(CONFIG_LRNG_DRNG_SWITCH)	+= lrng_switch.o
diff --git a/drivers/char/lrng/lrng_switch.c b/drivers/char/lrng/lrng_switch.c
new file mode 100644
index 000000000000..48c9a364aecf
--- /dev/null
+++ b/drivers/char/lrng/lrng_switch.c
@@ -0,0 +1,183 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG DRNG switching support
+ *
+ * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/lrng.h>
+
+#include "lrng_internal.h"
+
+static int lrng_drng_switch(struct lrng_drng *drng_store,
+			    const struct lrng_crypto_cb *cb, int node)
+{
+	const struct lrng_crypto_cb *old_cb;
+	unsigned long flags = 0;
+	int ret;
+	u8 seed[LRNG_DRNG_SECURITY_STRENGTH_BYTES];
+	void *new_drng = cb->lrng_drng_alloc(LRNG_DRNG_SECURITY_STRENGTH_BYTES);
+	void *old_drng, *new_hash, *old_hash;
+	bool sl = false, reset_drng = !lrng_get_available();
+
+	if (IS_ERR(new_drng)) {
+		pr_warn("could not allocate new DRNG for NUMA node %d (%ld)\n",
+			node, PTR_ERR(new_drng));
+		return PTR_ERR(new_drng);
+	}
+
+	new_hash = cb->lrng_hash_alloc(seed, sizeof(seed));
+	if (IS_ERR(new_hash)) {
+		pr_warn("could not allocate new LRNG pool hash (%ld)\n",
+			PTR_ERR(new_hash));
+		cb->lrng_drng_dealloc(new_drng);
+		return PTR_ERR(new_hash);
+	}
+
+	lrng_drng_lock(drng_store, &flags);
+
+	/*
+	 * Pull from existing DRNG to seed new DRNG regardless of seed status
+	 * of old DRNG -- the entropy state for the DRNG is left unchanged which
+	 * implies that als the new DRNG is reseeded when deemed necessary. This
+	 * seeding of the new DRNG shall only ensure that the new DRNG has the
+	 * same entropy as the old DRNG.
+	 */
+	ret = drng_store->crypto_cb->lrng_drng_generate_helper(
+				drng_store->drng, seed, sizeof(seed));
+	lrng_drng_unlock(drng_store, &flags);
+
+	if (ret < 0) {
+		reset_drng = true;
+		pr_warn("getting random data from DRNG failed for NUMA node %d "
+			"(%d)\n", node, ret);
+	} else {
+		/* seed new DRNG with data */
+		ret = cb->lrng_drng_seed_helper(new_drng, seed, ret);
+		if (ret < 0) {
+			reset_drng = true;
+			pr_warn("seeding of new DRNG failed for NUMA node %d "
+				"(%d)\n", node, ret);
+		} else {
+			pr_debug("seeded new DRNG of NUMA node %d instance "
+				 "from old DRNG instance\n", node);
+		}
+	}
+
+	mutex_lock(&drng_store->lock);
+	/*
+	 * If we switch the DRNG from the initial ChaCha20 DRNG to something
+	 * else, there is a lock transition from spin lock to mutex (see
+	 * lrng_drng_is_atomic and how the lock is taken in lrng_drng_lock).
+	 * Thus, we need to take both locks during the transition phase.
+	 */
+	if (lrng_drng_is_atomic(drng_store)) {
+		spin_lock_irqsave(&drng_store->spin_lock, flags);
+		sl = true;
+	}
+
+	if (reset_drng)
+		lrng_drng_reset(drng_store);
+
+	old_drng = drng_store->drng;
+	old_cb = drng_store->crypto_cb;
+	drng_store->drng = new_drng;
+	drng_store->crypto_cb = cb;
+
+	old_hash = drng_store->hash;
+	drng_store->hash = new_hash;
+	pr_info("Entropy pool read-hash allocated for DRNG for NUMA node %d\n",
+		node);
+
+	if (sl)
+		spin_unlock_irqrestore(&drng_store->spin_lock, flags);
+	mutex_unlock(&drng_store->lock);
+
+	/* ChaCha20 serves as atomic instance left untouched. */
+	if (old_drng != &chacha20) {
+		old_cb->lrng_drng_dealloc(old_drng);
+		old_cb->lrng_hash_dealloc(old_hash);
+	}
+
+	pr_info("DRNG of NUMA node %d switched\n", node);
+
+	return 0;
+}
+
+/*
+ * Switch the existing DRNG instances with new using the new crypto callbacks.
+ * The caller must hold the lrng_crypto_cb_update lock.
+ */
+static int lrng_drngs_switch(const struct lrng_crypto_cb *cb)
+{
+	struct lrng_drng **lrng_drng = lrng_drng_instances();
+	struct lrng_drng *lrng_drng_init = lrng_drng_init_instance();
+	int ret = 0;
+
+	/* Update DRNG */
+	if (lrng_drng) {
+		u32 node;
+
+		for_each_online_node(node) {
+			if (lrng_drng[node])
+				ret = lrng_drng_switch(lrng_drng[node], cb,
+						       node);
+		}
+	} else {
+		ret = lrng_drng_switch(lrng_drng_init, cb, 0);
+	}
+
+	if (!ret)
+		lrng_set_available();
+
+	return 0;
+}
+
+/**
+ * lrng_set_drng_cb - Register new cryptographic callback functions for DRNG
+ * The registering implies that all old DRNG states are replaced with new
+ * DRNG states.
+ *
+ * @cb: Callback functions to be registered -- if NULL, use the default
+ *	callbacks pointing to the ChaCha20 DRNG.
+ *
+ * Return:
+ * * 0 on success
+ * * < 0 on error
+ */
+int lrng_set_drng_cb(const struct lrng_crypto_cb *cb)
+{
+	struct lrng_drng *lrng_drng_init = lrng_drng_init_instance();
+	int ret;
+
+	if (!cb)
+		cb = &lrng_cc20_crypto_cb;
+
+	mutex_lock(&lrng_crypto_cb_update);
+
+	/*
+	 * If a callback other than the default is set, allow it only to be
+	 * set back to the default callback. This ensures that multiple
+	 * different callbacks can be registered at the same time. If a
+	 * callback different from the current callback and the default
+	 * callback shall be set, the current callback must be deregistered
+	 * (e.g. the kernel module providing it must be unloaded) and the new
+	 * implementation can be registered.
+	 */
+	if ((cb != &lrng_cc20_crypto_cb) &&
+	    (lrng_drng_init->crypto_cb != &lrng_cc20_crypto_cb)) {
+		pr_warn("disallow setting new cipher callbacks, unload the old "
+			"callbacks first!\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	ret = lrng_drngs_switch(cb);
+
+out:
+	mutex_unlock(&lrng_crypto_cb_update);
+	return ret;
+}
+EXPORT_SYMBOL(lrng_set_drng_cb);
-- 
2.24.1





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v28 05/12] crypto: DRBG - externalize DRBG functions for LRNG
  2020-01-15 10:31       ` [PATCH v28 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                           ` (3 preceding siblings ...)
  2020-01-15 10:32         ` [PATCH v28 04/12] LRNG - add switchable DRNG support Stephan Müller
@ 2020-01-15 10:33         ` Stephan Müller
  2020-01-15 10:33         ` [PATCH v28 06/12] LRNG - add SP800-90A DRBG extension Stephan Müller
                           ` (7 subsequent siblings)
  12 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2020-01-15 10:33 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap, Julia Lawall, Dan Carpenter

This patch allows several DRBG functions to be called by the LRNG kernel
code paths outside the drbg.c file.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 crypto/drbg.c         | 16 ++++++++++------
 include/crypto/drbg.h |  7 +++++++
 2 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/crypto/drbg.c b/crypto/drbg.c
index b6929eb5f565..5561dd0f09e1 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -113,7 +113,7 @@
  * the SHA256 / AES 256 over other ciphers. Thus, the favored
  * DRBGs are the latest entries in this array.
  */
-static const struct drbg_core drbg_cores[] = {
+const struct drbg_core drbg_cores[] = {
 #ifdef CONFIG_CRYPTO_DRBG_CTR
 	{
 		.flags = DRBG_CTR | DRBG_STRENGTH128,
@@ -190,6 +190,7 @@ static const struct drbg_core drbg_cores[] = {
 	},
 #endif /* CONFIG_CRYPTO_DRBG_HMAC */
 };
+EXPORT_SYMBOL(drbg_cores);
 
 static int drbg_uninstantiate(struct drbg_state *drbg);
 
@@ -205,7 +206,7 @@ static int drbg_uninstantiate(struct drbg_state *drbg);
  * Return: normalized strength in *bytes* value or 32 as default
  *	   to counter programming errors
  */
-static inline unsigned short drbg_sec_strength(drbg_flag_t flags)
+unsigned short drbg_sec_strength(drbg_flag_t flags)
 {
 	switch (flags & DRBG_STRENGTH_MASK) {
 	case DRBG_STRENGTH128:
@@ -218,6 +219,7 @@ static inline unsigned short drbg_sec_strength(drbg_flag_t flags)
 		return 32;
 	}
 }
+EXPORT_SYMBOL(drbg_sec_strength);
 
 /*
  * FIPS 140-2 continuous self test for the noise source
@@ -1202,7 +1204,7 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
 }
 
 /* Free all substructures in a DRBG state without the DRBG state structure */
-static inline void drbg_dealloc_state(struct drbg_state *drbg)
+void drbg_dealloc_state(struct drbg_state *drbg)
 {
 	if (!drbg)
 		return;
@@ -1223,12 +1225,13 @@ static inline void drbg_dealloc_state(struct drbg_state *drbg)
 		drbg->fips_primed = false;
 	}
 }
+EXPORT_SYMBOL(drbg_dealloc_state);
 
 /*
  * Allocate all sub-structures for a DRBG state.
  * The DRBG state structure must already be allocated.
  */
-static inline int drbg_alloc_state(struct drbg_state *drbg)
+int drbg_alloc_state(struct drbg_state *drbg)
 {
 	int ret = -ENOMEM;
 	unsigned int sb_size = 0;
@@ -1307,6 +1310,7 @@ static inline int drbg_alloc_state(struct drbg_state *drbg)
 	drbg_dealloc_state(drbg);
 	return ret;
 }
+EXPORT_SYMBOL(drbg_alloc_state);
 
 /*************************************************************************
  * DRBG interface functions
@@ -1874,8 +1878,7 @@ static int drbg_kcapi_sym_ctr(struct drbg_state *drbg,
  *
  * return: flags
  */
-static inline void drbg_convert_tfm_core(const char *cra_driver_name,
-					 int *coreref, bool *pr)
+void drbg_convert_tfm_core(const char *cra_driver_name, int *coreref, bool *pr)
 {
 	int i = 0;
 	size_t start = 0;
@@ -1902,6 +1905,7 @@ static inline void drbg_convert_tfm_core(const char *cra_driver_name,
 		}
 	}
 }
+EXPORT_SYMBOL(drbg_convert_tfm_core);
 
 static int drbg_kcapi_init(struct crypto_tfm *tfm)
 {
diff --git a/include/crypto/drbg.h b/include/crypto/drbg.h
index 8c9af21efce1..c63b20375235 100644
--- a/include/crypto/drbg.h
+++ b/include/crypto/drbg.h
@@ -282,4 +282,11 @@ enum drbg_prefixes {
 	DRBG_PREFIX3
 };
 
+extern int drbg_alloc_state(struct drbg_state *drbg);
+extern void drbg_dealloc_state(struct drbg_state *drbg);
+extern void drbg_convert_tfm_core(const char *cra_driver_name, int *coreref,
+				  bool *pr);
+extern const struct drbg_core drbg_cores[];
+extern unsigned short drbg_sec_strength(drbg_flag_t flags);
+
 #endif /* _DRBG_H */
-- 
2.24.1





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v28 06/12] LRNG - add SP800-90A DRBG extension
  2020-01-15 10:31       ` [PATCH v28 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                           ` (4 preceding siblings ...)
  2020-01-15 10:33         ` [PATCH v28 05/12] crypto: DRBG - externalize DRBG functions for LRNG Stephan Müller
@ 2020-01-15 10:33         ` Stephan Müller
  2020-01-16  0:14           ` Randy Dunlap
  2020-01-15 10:34         ` [PATCH v28 07/12] LRNG - add kernel crypto API PRNG extension Stephan Müller
                           ` (6 subsequent siblings)
  12 siblings, 1 reply; 162+ messages in thread
From: Stephan Müller @ 2020-01-15 10:33 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap, Julia Lawall, Dan Carpenter

Using the LRNG switchable DRNG support, the SP800-90A DRBG extension is
implemented.

The DRBG uses the kernel crypto API DRBG implementation. In addition, it
uses the kernel crypto API SHASH support to provide the hashing
operation.

The DRBG supports the choice of either a CTR DRBG using AES-256, HMAC
DRBG with SHA-512 core or Hash DRBG with SHA-512 core. The used core can
be selected with the module parameter lrng_drbg_type. The default is the
CTR DRBG.

When compiling the DRBG extension statically, the DRBG is loaded at
late_initcall stage which implies that with the start of user space, the
user space interfaces of getrandom(2), /dev/random and /dev/urandom
provide random data produced by an SP800-90A DRBG.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Kconfig     |  11 ++
 drivers/char/lrng/Makefile    |   1 +
 drivers/char/lrng/lrng_drbg.c | 260 ++++++++++++++++++++++++++++++++++
 3 files changed, 272 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_drbg.c

diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
index cb701bb0b8b6..15fb623d9d1f 100644
--- a/drivers/char/lrng/Kconfig
+++ b/drivers/char/lrng/Kconfig
@@ -71,4 +71,15 @@ menuconfig LRNG_DRNG_SWITCH
 	  accessible via the external interfaces. With this configuration
 	  option other DRNGs can be selected and loaded at runtime.
 
+if LRNG_DRNG_SWITCH
+config LRNG_DRBG
+	tristate "SP800-90A support for the LRNG"
+	select CRYPTO_DRBG_MENU
+	select CRYPTO_CMAC if CRYPTO_DRBG_CTR
+	help
+	  Enable the SP800-90A DRBG support for the LRNG. Once the
+	  module is loaded, output from /dev/random, /dev/urandom,
+	  getrandom(2), or get_random_bytes is provided by a DRBG.
+endif # LRNG_DRNG_SWITCH
+
 endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index 31cfe87c999e..0d320fcb7b9e 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -11,3 +11,4 @@ obj-y				+= lrng_pool.o lrng_aux.o \
 obj-$(CONFIG_NUMA)		+= lrng_numa.o
 obj-$(CONFIG_SYSCTL)		+= lrng_proc.o
 obj-$(CONFIG_LRNG_DRNG_SWITCH)	+= lrng_switch.o
+obj-$(CONFIG_LRNG_DRBG)		+= lrng_drbg.o
diff --git a/drivers/char/lrng/lrng_drbg.c b/drivers/char/lrng/lrng_drbg.c
new file mode 100644
index 000000000000..8bf2badb1fe0
--- /dev/null
+++ b/drivers/char/lrng/lrng_drbg.c
@@ -0,0 +1,260 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * Backend for the LRNG providing the cryptographic primitives using the
+ * kernel crypto API and its DRBG.
+ *
+ * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <crypto/drbg.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/lrng.h>
+
+/*
+ * Define a DRBG plus a hash / MAC used to extract data from the entropy pool.
+ * For LRNG_HASH_NAME you can use a hash or a MAC (HMAC or CMAC) of your choice
+ * (Note, you should use the suggested selections below -- using SHA-1 or MD5
+ * is not wise). The idea is that the used cipher primitive can be selected to
+ * be the same as used for the DRBG. I.e. the LRNG only uses one cipher
+ * primitive using the same cipher implementation with the options offered in
+ * the following. This means, if the CTR DRBG is selected and AES-NI is present,
+ * both the CTR DRBG and the selected cmac(aes) use AES-NI.
+ *
+ * The security strengths of the DRBGs are all 256 bits according to
+ * SP800-57 section 5.6.1.
+ *
+ * This definition is allowed to be changed.
+ */
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+static unsigned int lrng_drbg_type = 0;
+#elif defined CONFIG_CRYPTO_DRBG_HMAC
+static unsigned int lrng_drbg_type = 1;
+#elif defined CONFIG_CRYPTO_DRBG_HASH
+static unsigned int lrng_drbg_type = 2;
+#else
+#error "Unknown DRBG in use"
+#endif
+
+/* The parameter must be r/o in sysfs as otherwise races appear. */
+module_param(lrng_drbg_type, uint, 0444);
+MODULE_PARM_DESC(lrng_drbg_type, "DRBG type used for LRNG (0->CTR_DRBG, "
+				 "1->HMAC_DRBG, 2->Hash_DRBG)");
+
+struct lrng_drbg {
+	const char *hash_name;
+	const char *drbg_core;
+};
+
+static const struct lrng_drbg lrng_drbg_types[] = {
+	{	/* CTR_DRBG with AES-256 using derivation function */
+		.hash_name = "cmac(aes)",
+		.drbg_core = "drbg_nopr_ctr_aes256",
+	}, {	/* HMAC_DRBG with SHA-512 */
+		.hash_name = "sha512",
+		.drbg_core = "drbg_nopr_hmac_sha512",
+	}, {	/* Hash_DRBG with SHA-512 using derivation function */
+		.hash_name = "sha512",
+		.drbg_core = "drbg_nopr_sha512"
+	}
+};
+
+struct lrng_hash_info {
+	struct shash_desc shash;
+	char ctx[];
+};
+
+static int lrng_drbg_drng_seed_helper(void *drng, const u8 *inbuf, u32 inbuflen)
+{
+	struct drbg_state *drbg = (struct drbg_state *)drng;
+	LIST_HEAD(seedlist);
+	struct drbg_string data;
+	int ret;
+
+	drbg_string_fill(&data, inbuf, inbuflen);
+	list_add_tail(&data.list, &seedlist);
+	ret = drbg->d_ops->update(drbg, &seedlist, drbg->seeded);
+
+	if (ret >= 0)
+		drbg->seeded = true;
+
+	return ret;
+}
+
+static int lrng_drbg_drng_generate_helper(void *drng, u8 *outbuf, u32 outbuflen)
+{
+	struct drbg_state *drbg = (struct drbg_state *)drng;
+
+	return drbg->d_ops->generate(drbg, outbuf, outbuflen, NULL);
+}
+
+static void *lrng_drbg_drng_alloc(u32 sec_strength)
+{
+	struct drbg_state *drbg;
+	int coreref = -1;
+	bool pr = false;
+	int ret;
+
+	drbg_convert_tfm_core(lrng_drbg_types[lrng_drbg_type].drbg_core,
+			      &coreref, &pr);
+	if (coreref < 0)
+		return ERR_PTR(-EFAULT);
+
+	drbg = kzalloc(sizeof(struct drbg_state), GFP_KERNEL);
+	if (!drbg)
+		return ERR_PTR(-ENOMEM);
+
+	drbg->core = &drbg_cores[coreref];
+	drbg->seeded = false;
+	ret = drbg_alloc_state(drbg);
+	if (ret)
+		goto err;
+
+	if (sec_strength > drbg_sec_strength(drbg->core->flags)) {
+		pr_err("Security strength of DRBG (%u bits) lower than "
+		       "requested by LRNG (%u bits)\n",
+			drbg_sec_strength(drbg->core->flags) * 8,
+			sec_strength * 8);
+		goto dealloc;
+	}
+
+	if (sec_strength < drbg_sec_strength(drbg->core->flags))
+		pr_warn("Security strength of DRBG (%u bits) higher than "
+			"requested by LRNG (%u bits)\n",
+			drbg_sec_strength(drbg->core->flags) * 8,
+			sec_strength * 8);
+
+	pr_info("DRBG with %s core allocated\n", drbg->core->backend_cra_name);
+
+	return drbg;
+
+dealloc:
+	if (drbg->d_ops)
+		drbg->d_ops->crypto_fini(drbg);
+	drbg_dealloc_state(drbg);
+err:
+	kfree(drbg);
+	return ERR_PTR(-EINVAL);
+}
+
+static void lrng_drbg_drng_dealloc(void *drng)
+{
+	struct drbg_state *drbg = (struct drbg_state *)drng;
+
+	drbg_dealloc_state(drbg);
+	kzfree(drbg);
+	pr_info("DRBG deallocated\n");
+}
+
+static void *lrng_drbg_hash_alloc(const u8 *key, u32 keylen)
+{
+	struct lrng_hash_info *lrng_hash;
+	struct crypto_shash *tfm;
+	int size, ret;
+
+	tfm = crypto_alloc_shash(lrng_drbg_types[lrng_drbg_type].hash_name,
+				 0, 0);
+	if (IS_ERR(tfm)) {
+		pr_err("could not allocate hash %s\n",
+		       lrng_drbg_types[lrng_drbg_type].hash_name);
+		return ERR_CAST(tfm);
+	}
+
+	size = sizeof(struct lrng_hash_info) + crypto_shash_descsize(tfm);
+	lrng_hash = kmalloc(size, GFP_KERNEL);
+	if (!lrng_hash) {
+		crypto_free_shash(tfm);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	lrng_hash->shash.tfm = tfm;
+
+	/* If the used hash is no MAC, ignore the ENOSYS return code */
+	ret = crypto_shash_setkey(tfm, key, keylen);
+	if (ret && ret != -ENOSYS) {
+		pr_err("could not set the key for MAC\n");
+		crypto_free_shash(tfm);
+		kfree(lrng_hash);
+		return ERR_PTR(ret);
+	}
+
+	pr_info("Hash %s allocated\n",
+		lrng_drbg_types[lrng_drbg_type].hash_name);
+
+	return lrng_hash;
+}
+
+static void lrng_drbg_hash_dealloc(void *hash)
+{
+	struct lrng_hash_info *lrng_hash = (struct lrng_hash_info *)hash;
+	struct shash_desc *shash = &lrng_hash->shash;
+	struct crypto_shash *tfm = shash->tfm;
+
+	crypto_free_shash(tfm);
+	kfree(lrng_hash);
+	pr_info("Hash deallocated\n");
+}
+
+static u32 lrng_drbg_hash_digestsize(void *hash)
+{
+	struct lrng_hash_info *lrng_hash = (struct lrng_hash_info *)hash;
+	struct shash_desc *shash = &lrng_hash->shash;
+
+	return crypto_shash_digestsize(shash->tfm);
+}
+
+static int lrng_drbg_hash_buffer(void *hash, const u8 *inbuf, u32 inbuflen,
+				 u8 *digest)
+{
+	struct lrng_hash_info *lrng_hash = (struct lrng_hash_info *)hash;
+	struct shash_desc *shash = &lrng_hash->shash;
+
+	return crypto_shash_digest(shash, inbuf, inbuflen, digest);
+}
+
+static const char *lrng_drbg_name(void)
+{
+	return lrng_drbg_types[lrng_drbg_type].drbg_core;
+}
+
+static const char *lrng_hash_name(void)
+{
+	return lrng_drbg_types[lrng_drbg_type].hash_name;
+}
+
+const static struct lrng_crypto_cb lrng_drbg_crypto_cb = {
+	.lrng_drng_name			= lrng_drbg_name,
+	.lrng_hash_name			= lrng_hash_name,
+	.lrng_drng_alloc		= lrng_drbg_drng_alloc,
+	.lrng_drng_dealloc		= lrng_drbg_drng_dealloc,
+	.lrng_drng_seed_helper		= lrng_drbg_drng_seed_helper,
+	.lrng_drng_generate_helper	= lrng_drbg_drng_generate_helper,
+	.lrng_hash_alloc		= lrng_drbg_hash_alloc,
+	.lrng_hash_dealloc		= lrng_drbg_hash_dealloc,
+	.lrng_hash_digestsize		= lrng_drbg_hash_digestsize,
+	.lrng_hash_buffer		= lrng_drbg_hash_buffer,
+};
+
+static int __init lrng_drbg_init(void)
+{
+	if (lrng_drbg_type >= ARRAY_SIZE(lrng_drbg_types)) {
+		pr_err("lrng_drbg_type parameter too large (given %u - max: %lu)",
+		       lrng_drbg_type,
+		       (unsigned long)ARRAY_SIZE(lrng_drbg_types) - 1);
+		return -EAGAIN;
+	}
+	return lrng_set_drng_cb(&lrng_drbg_crypto_cb);
+}
+
+static void __exit lrng_drbg_exit(void)
+{
+	lrng_set_drng_cb(NULL);
+}
+
+late_initcall(lrng_drbg_init);
+module_exit(lrng_drbg_exit);
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
+MODULE_DESCRIPTION("Linux Random Number Generator - SP800-90A DRBG backend");
-- 
2.24.1





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v28 07/12] LRNG - add kernel crypto API PRNG extension
  2020-01-15 10:31       ` [PATCH v28 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                           ` (5 preceding siblings ...)
  2020-01-15 10:33         ` [PATCH v28 06/12] LRNG - add SP800-90A DRBG extension Stephan Müller
@ 2020-01-15 10:34         ` Stephan Müller
  2020-01-16  0:15           ` Randy Dunlap
  2020-01-15 10:34         ` [PATCH v28 08/12] crypto: provide access to a static Jitter RNG state Stephan Müller
                           ` (5 subsequent siblings)
  12 siblings, 1 reply; 162+ messages in thread
From: Stephan Müller @ 2020-01-15 10:34 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap, Julia Lawall, Dan Carpenter

Add runtime-pluggable support for all PRNGs that are accessible via
the kernel crypto API, including hardware PRNGs. The PRNG is selected
with the module parameter drng_name where the name must be one that the
kernel crypto API can resolve into an RNG.

This allows using of the kernel crypto API PRNG implementations that
provide an interface to hardware PRNGs. Using this extension,
the LRNG uses the hardware PRNGs to generate random numbers. An
example is the S390 CPACF support providing such a PRNG.

The hash is provided by a kernel crypto API SHASH whose digest size
complies with the seedsize of the PRNG.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Kconfig      |  10 +
 drivers/char/lrng/Makefile     |   1 +
 drivers/char/lrng/lrng_kcapi.c | 327 +++++++++++++++++++++++++++++++++
 3 files changed, 338 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_kcapi.c

diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
index 15fb623d9d1f..0d070a3897dd 100644
--- a/drivers/char/lrng/Kconfig
+++ b/drivers/char/lrng/Kconfig
@@ -80,6 +80,16 @@ config LRNG_DRBG
 	  Enable the SP800-90A DRBG support for the LRNG. Once the
 	  module is loaded, output from /dev/random, /dev/urandom,
 	  getrandom(2), or get_random_bytes is provided by a DRBG.
+
+config LRNG_KCAPI
+	tristate "Kernel Crypto API support for the LRNG"
+	select CRYPTO_RNG
+	help
+	  Enable the support for generic pseudo-random number
+	  generators offered by the kernel crypto API with the
+	  LRNG. Once the module is loaded, output from /dev/random,
+	  /dev/urandom, getrandom(2), or get_random_bytes is
+	  provided by the selected kernel crypto API RNG.
 endif # LRNG_DRNG_SWITCH
 
 endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index 0d320fcb7b9e..94b2dfb2dfdb 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -12,3 +12,4 @@ obj-$(CONFIG_NUMA)		+= lrng_numa.o
 obj-$(CONFIG_SYSCTL)		+= lrng_proc.o
 obj-$(CONFIG_LRNG_DRNG_SWITCH)	+= lrng_switch.o
 obj-$(CONFIG_LRNG_DRBG)		+= lrng_drbg.o
+obj-$(CONFIG_LRNG_KCAPI)	+= lrng_kcapi.o
diff --git a/drivers/char/lrng/lrng_kcapi.c b/drivers/char/lrng/lrng_kcapi.c
new file mode 100644
index 000000000000..115af147bd5c
--- /dev/null
+++ b/drivers/char/lrng/lrng_kcapi.c
@@ -0,0 +1,327 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * Backend for the LRNG providing the cryptographic primitives using the
+ * kernel crypto API.
+ *
+ * Copyright (C) 2018 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <crypto/hash.h>
+#include <crypto/rng.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/lrng.h>
+
+static char *drng_name = NULL;
+module_param(drng_name, charp, 0444);
+MODULE_PARM_DESC(drng_name, "Kernel crypto API name of DRNG");
+
+static char *pool_hash = "sha512";
+module_param(pool_hash, charp, 0444);
+MODULE_PARM_DESC(pool_hash,
+		 "Kernel crypto API name of hash or keyed message digest to read the entropy pool");
+
+static char *seed_hash = NULL;
+module_param(seed_hash, charp, 0444);
+MODULE_PARM_DESC(seed_hash,
+		 "Kernel crypto API name of hash with output size equal to seedsize of DRNG to bring seed string to the size required by the DRNG");
+
+struct lrng_hash_info {
+	struct shash_desc shash;
+	char ctx[];
+};
+
+struct lrng_drng_info {
+	struct crypto_rng *kcapi_rng;
+	struct lrng_hash_info *lrng_hash;
+};
+
+static struct lrng_hash_info *_lrng_kcapi_hash_alloc(const char *name)
+{
+	struct lrng_hash_info *lrng_hash;
+	struct crypto_shash *tfm;
+	int size;
+
+	if (!name) {
+		pr_err("Hash name missing\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	tfm = crypto_alloc_shash(name, 0, 0);
+	if (IS_ERR(tfm)) {
+		pr_err("could not allocate hash %s\n", name);
+		return ERR_CAST(tfm);
+	}
+
+	size = sizeof(struct lrng_hash_info) + crypto_shash_descsize(tfm);
+	lrng_hash = kmalloc(size, GFP_KERNEL);
+	if (!lrng_hash) {
+		crypto_free_shash(tfm);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	lrng_hash->shash.tfm = tfm;
+
+	return lrng_hash;
+}
+
+static inline u32 _lrng_kcapi_hash_digestsize(struct lrng_hash_info *lrng_hash)
+{
+	struct shash_desc *shash = &lrng_hash->shash;
+	struct crypto_shash *tfm = shash->tfm;
+
+	return crypto_shash_digestsize(tfm);
+}
+
+static inline void _lrng_kcapi_hash_free(struct lrng_hash_info *lrng_hash)
+{
+	struct shash_desc *shash = &lrng_hash->shash;
+	struct crypto_shash *tfm = shash->tfm;
+
+	crypto_free_shash(tfm);
+	kfree(lrng_hash);
+}
+
+static void *lrng_kcapi_hash_alloc(const u8 *key, u32 keylen)
+{
+	struct lrng_hash_info *lrng_hash;
+	int ret;
+
+	lrng_hash = _lrng_kcapi_hash_alloc(pool_hash);
+	if (IS_ERR(lrng_hash))
+		return ERR_CAST(lrng_hash);
+
+	/* If the used hash is no MAC, ignore the ENOSYS return code */
+	ret = crypto_shash_setkey(lrng_hash->shash.tfm, key, keylen);
+	if (ret && ret != -ENOSYS) {
+		pr_err("could not set the key for MAC\n");
+		_lrng_kcapi_hash_free(lrng_hash);
+		return ERR_PTR(ret);
+	}
+
+	pr_info("Hash %s allocated\n", pool_hash);
+
+	return lrng_hash;
+}
+
+static void lrng_kcapi_hash_dealloc(void *hash)
+{
+	struct lrng_hash_info *lrng_hash = (struct lrng_hash_info *)hash;
+
+	_lrng_kcapi_hash_free(lrng_hash);
+	pr_info("Hash %s deallocated\n", pool_hash);
+}
+
+static u32 lrng_kcapi_hash_digestsize(void *hash)
+{
+	struct lrng_hash_info *lrng_hash = (struct lrng_hash_info *)hash;
+
+	return _lrng_kcapi_hash_digestsize(lrng_hash);
+}
+
+static int lrng_kcapi_hash_buffer(void *hash, const u8 *inbuf, u32 inbuflen,
+				  u8 *digest)
+{
+	struct lrng_hash_info *lrng_hash = (struct lrng_hash_info *)hash;
+	struct shash_desc *shash = &lrng_hash->shash;
+
+	return crypto_shash_digest(shash, inbuf, inbuflen, digest);
+}
+
+static int lrng_kcapi_drng_seed_helper(void *drng, const u8 *inbuf,
+				       u32 inbuflen)
+{
+	struct lrng_drng_info *lrng_drng_info = (struct lrng_drng_info *)drng;
+	struct crypto_rng *kcapi_rng = lrng_drng_info->kcapi_rng;
+	struct lrng_hash_info *lrng_hash = lrng_drng_info->lrng_hash;
+
+	if (lrng_hash) {
+		struct shash_desc *shash = &lrng_hash->shash;
+		u32 digestsize = _lrng_kcapi_hash_digestsize(lrng_hash);
+		u8 digest[64] __aligned(8);
+		int ret;
+
+		BUG_ON(digestsize > sizeof(digest));
+
+		ret = crypto_shash_digest(shash, inbuf, inbuflen, digest);
+		if (ret)
+			return ret;
+
+		ret = crypto_rng_reset(kcapi_rng, digest, digestsize);
+		if (ret)
+			return ret;
+
+		memzero_explicit(digest, digestsize);
+
+		return 0;
+	} else {
+		return crypto_rng_reset(kcapi_rng, inbuf, inbuflen);
+	}
+}
+
+static int lrng_kcapi_drng_generate_helper(void *drng, u8 *outbuf,
+					   u32 outbuflen)
+{
+	struct lrng_drng_info *lrng_drng_info = (struct lrng_drng_info *)drng;
+	struct crypto_rng *kcapi_rng = lrng_drng_info->kcapi_rng;
+	int ret = crypto_rng_get_bytes(kcapi_rng, outbuf, outbuflen);
+
+	if (ret < 0)
+		return ret;
+
+	return outbuflen;
+}
+
+static void *lrng_kcapi_drng_alloc(u32 sec_strength)
+{
+	struct lrng_drng_info *lrng_drng_info;
+	struct crypto_rng *kcapi_rng;
+	int seedsize;
+	void *ret =  ERR_PTR(-ENOMEM);
+
+	if (!drng_name) {
+		pr_err("DRNG name missing\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (!memcmp(drng_name, "drbg", 4)) {
+		pr_err("SP800-90A DRBG cannot be allocated using lrng_kcapi "
+		       "backend, use lrng_drbg backend instead\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (!memcmp(drng_name, "stdrng", 6)) {
+		pr_err("stdrng cannot be allocated using lrng_kcapi backend, "
+		       "it is too unspecific and potentially may allocate the "
+		       "DRBG\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	lrng_drng_info = kmalloc(sizeof(*lrng_drng_info), GFP_KERNEL);
+	if (!lrng_drng_info)
+		return ERR_PTR(-ENOMEM);
+
+	kcapi_rng = crypto_alloc_rng(drng_name, 0, 0);
+	if (IS_ERR(kcapi_rng)) {
+		pr_err("DRNG %s cannot be allocated\n", drng_name);
+		ret = ERR_CAST(kcapi_rng);
+		goto free;
+	}
+	lrng_drng_info->kcapi_rng = kcapi_rng;
+
+	seedsize =  crypto_rng_seedsize(kcapi_rng);
+
+	if (sec_strength > seedsize)
+		pr_info("Seedsize DRNG (%u bits) lower than "
+			"security strength of LRNG noise source (%u bits)\n",
+			crypto_rng_seedsize(kcapi_rng) * 8,
+			sec_strength * 8);
+
+	if (seedsize) {
+		struct lrng_hash_info *lrng_hash;
+
+		if (!seed_hash) {
+			switch (seedsize) {
+			case 32:
+				seed_hash = "sha256";
+				break;
+			case 48:
+				seed_hash = "sha384";
+				break;
+			case 64:
+				seed_hash = "sha512";
+				break;
+			default:
+				pr_err("Seed size %d cannot be processed\n",
+				       seedsize);
+				goto dealloc;
+				break;
+			}
+		}
+
+		lrng_hash = _lrng_kcapi_hash_alloc(seed_hash);
+		if (IS_ERR(lrng_hash)) {
+			ret = ERR_CAST(lrng_hash);
+			goto dealloc;
+		}
+
+		if (seedsize != _lrng_kcapi_hash_digestsize(lrng_hash)) {
+			pr_err("Seed hash output size not equal to DRNG seed "
+			       "size\n");
+			_lrng_kcapi_hash_free(lrng_hash);
+			ret = ERR_PTR(-EINVAL);
+			goto dealloc;
+		}
+
+		lrng_drng_info->lrng_hash = lrng_hash;
+
+		pr_info("Seed hash %s allocated\n", seed_hash);
+	} else {
+		lrng_drng_info->lrng_hash = NULL;
+	}
+
+	pr_info("Kernel crypto API DRNG %s allocated\n", drng_name);
+
+	return lrng_drng_info;
+
+dealloc:
+	crypto_free_rng(kcapi_rng);
+free:
+	kfree(lrng_drng_info);
+	return ret;
+}
+
+static void lrng_kcapi_drng_dealloc(void *drng)
+{
+	struct lrng_drng_info *lrng_drng_info = (struct lrng_drng_info *)drng;
+	struct crypto_rng *kcapi_rng = lrng_drng_info->kcapi_rng;
+	struct lrng_hash_info *lrng_hash = lrng_drng_info->lrng_hash;
+
+	crypto_free_rng(kcapi_rng);
+	if (lrng_hash) {
+		_lrng_kcapi_hash_free(lrng_hash);
+		pr_info("Seed hash %s deallocated\n", seed_hash);
+	}
+	kfree(lrng_drng_info);
+	pr_info("DRNG %s deallocated\n", drng_name);
+}
+
+static const char *lrng_kcapi_drng_name(void)
+{
+	return drng_name;
+}
+
+static const char *lrng_kcapi_pool_hash(void)
+{
+	return pool_hash;
+}
+
+const static struct lrng_crypto_cb lrng_kcapi_crypto_cb = {
+	.lrng_drng_name			= lrng_kcapi_drng_name,
+	.lrng_hash_name			= lrng_kcapi_pool_hash,
+	.lrng_drng_alloc		= lrng_kcapi_drng_alloc,
+	.lrng_drng_dealloc		= lrng_kcapi_drng_dealloc,
+	.lrng_drng_seed_helper		= lrng_kcapi_drng_seed_helper,
+	.lrng_drng_generate_helper	= lrng_kcapi_drng_generate_helper,
+	.lrng_hash_alloc		= lrng_kcapi_hash_alloc,
+	.lrng_hash_dealloc		= lrng_kcapi_hash_dealloc,
+	.lrng_hash_digestsize		= lrng_kcapi_hash_digestsize,
+	.lrng_hash_buffer		= lrng_kcapi_hash_buffer,
+};
+
+static int __init lrng_kcapi_init(void)
+{
+	return lrng_set_drng_cb(&lrng_kcapi_crypto_cb);
+}
+static void __exit lrng_kcapi_exit(void)
+{
+	lrng_set_drng_cb(NULL);
+}
+
+late_initcall(lrng_kcapi_init);
+module_exit(lrng_kcapi_exit);
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
+MODULE_DESCRIPTION("Linux Random Number Generator - kernel crypto API DRNG backend");
-- 
2.24.1





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v28 08/12] crypto: provide access to a static Jitter RNG state
  2020-01-15 10:31       ` [PATCH v28 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                           ` (6 preceding siblings ...)
  2020-01-15 10:34         ` [PATCH v28 07/12] LRNG - add kernel crypto API PRNG extension Stephan Müller
@ 2020-01-15 10:34         ` Stephan Müller
  2020-01-15 10:34         ` [PATCH v28 09/12] LRNG - add Jitter RNG fast noise source Stephan Müller
                           ` (4 subsequent siblings)
  12 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2020-01-15 10:34 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap, Julia Lawall, Dan Carpenter

To support the LRNG operation which uses the Jitter RNG separately
from the kernel crypto API, at a time where potentially the regular
memory management is not yet initialized, the Jitter RNG needs to
provide a state whose memory is defined at compile time. As only once
instance will ever be needed by the LRNG, define once static memory
block which is solely to be used by the LRNG.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 crypto/jitterentropy-kcapi.c                  |  3 +--
 crypto/jitterentropy.c                        | 25 ++++++++++++++++++-
 .../crypto/internal}/jitterentropy.h          |  3 +++
 3 files changed, 28 insertions(+), 3 deletions(-)
 rename {crypto => include/crypto/internal}/jitterentropy.h (84%)

diff --git a/crypto/jitterentropy-kcapi.c b/crypto/jitterentropy-kcapi.c
index a5ce8f96790f..11b00e9f37f3 100644
--- a/crypto/jitterentropy-kcapi.c
+++ b/crypto/jitterentropy-kcapi.c
@@ -43,8 +43,7 @@
 #include <linux/time.h>
 #include <linux/crypto.h>
 #include <crypto/internal/rng.h>
-
-#include "jitterentropy.h"
+#include <crypto/internal/jitterentropy.h>
 
 /***************************************************************************
  * Helper function
diff --git a/crypto/jitterentropy.c b/crypto/jitterentropy.c
index 042157f0d28b..529c9db13e64 100644
--- a/crypto/jitterentropy.c
+++ b/crypto/jitterentropy.c
@@ -103,7 +103,7 @@ struct rand_data {
  * Helper functions
  ***************************************************************************/
 
-#include "jitterentropy.h"
+#include <crypto/internal/jitterentropy.h>
 
 /**
  * Update of the loop count used for the next round of
@@ -639,3 +639,26 @@ int jent_entropy_init(void)
 
 	return 0;
 }
+
+struct rand_data *jent_lrng_entropy_collector(void)
+{
+	static unsigned char lrng_jent_mem[JENT_MEMORY_SIZE];
+	static struct rand_data lrng_jent_state = {
+		.data		= 0,
+		.old_data	= 0,
+		.prev_time	= 0,
+		.last_delta	= 0,
+		.last_delta2	= 0,
+		.osr		= 1,
+		.mem		= lrng_jent_mem,
+		.memlocation	= 0,
+		.memblocks	= JENT_MEMORY_BLOCKSIZE,
+		.memblocksize	= JENT_MEMORY_BLOCKS,
+		.memaccessloops	= JENT_MEMORY_ACCESSLOOPS,
+	};
+
+	if (jent_entropy_init())
+		return NULL;
+
+	return &lrng_jent_state;
+}
diff --git a/crypto/jitterentropy.h b/include/crypto/internal/jitterentropy.h
similarity index 84%
rename from crypto/jitterentropy.h
rename to include/crypto/internal/jitterentropy.h
index c83fff32d130..6e07d86eac82 100644
--- a/crypto/jitterentropy.h
+++ b/include/crypto/internal/jitterentropy.h
@@ -15,3 +15,6 @@ extern int jent_read_entropy(struct rand_data *ec, unsigned char *data,
 extern struct rand_data *jent_entropy_collector_alloc(unsigned int osr,
 						      unsigned int flags);
 extern void jent_entropy_collector_free(struct rand_data *entropy_collector);
+
+/* Access to statically allocated Jitter RNG instance */
+extern struct rand_data *jent_lrng_entropy_collector(void);
-- 
2.24.1





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v28 09/12] LRNG - add Jitter RNG fast noise source
  2020-01-15 10:31       ` [PATCH v28 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                           ` (7 preceding siblings ...)
  2020-01-15 10:34         ` [PATCH v28 08/12] crypto: provide access to a static Jitter RNG state Stephan Müller
@ 2020-01-15 10:34         ` Stephan Müller
  2020-01-16  0:17           ` Randy Dunlap
  2020-01-15 10:35         ` [PATCH v28 10/12] LRNG - add SP800-90B compliant health tests Stephan Müller
                           ` (3 subsequent siblings)
  12 siblings, 1 reply; 162+ messages in thread
From: Stephan Müller @ 2020-01-15 10:34 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap, Julia Lawall, Dan Carpenter

From 1666398d358388d0476f79019e0a6116c30db8a4 Mon Sep 17 00:00:00 2001
From: Stephan Mueller <smueller@chronox.de>
Date: Sun, 12 Jan 2020 11:56:31 +0100
Subject: [PATCH v28 09/12] LRNG - add Jitter RNG fast noise source
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The Jitter RNG fast noise source implemented as part of the kernel
crypto API is queried for 256 bits of entropy at the time the seed
buffer managed by the LRNG is about to be filled.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Kconfig     | 11 +++++
 drivers/char/lrng/Makefile    |  1 +
 drivers/char/lrng/lrng_jent.c | 89 +++++++++++++++++++++++++++++++++++
 3 files changed, 101 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_jent.c

diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
index 0d070a3897dd..10b7cbdb8c8e 100644
--- a/drivers/char/lrng/Kconfig
+++ b/drivers/char/lrng/Kconfig
@@ -92,4 +92,15 @@ config LRNG_KCAPI
 	  provided by the selected kernel crypto API RNG.
 endif # LRNG_DRNG_SWITCH
 
+config LRNG_JENT
+	bool "Enable Jitter RNG as LRNG Seed Source"
+	select CRYPTO_JITTERENTROPY
+	help
+	  The Linux RNG may use the Jitter RNG as noise source. Enabling
+	  this option enables the use of the Jitter RNG. Its default
+	  entropy level is 16 bits of entropy per 256 data bits delivered
+	  by the Jitter RNG. This entropy level can be changed at boot
+	  time or at runtime with the lrng_base.jitterrng configuration
+	  variable.
+
 endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index 94b2dfb2dfdb..4f5b6f38f0c4 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -13,3 +13,4 @@ obj-$(CONFIG_SYSCTL)		+= lrng_proc.o
 obj-$(CONFIG_LRNG_DRNG_SWITCH)	+= lrng_switch.o
 obj-$(CONFIG_LRNG_DRBG)		+= lrng_drbg.o
 obj-$(CONFIG_LRNG_KCAPI)	+= lrng_kcapi.o
+obj-$(CONFIG_LRNG_JENT)		+= lrng_jent.o
diff --git a/drivers/char/lrng/lrng_jent.c b/drivers/char/lrng/lrng_jent.c
new file mode 100644
index 000000000000..ff0bbe2680c4
--- /dev/null
+++ b/drivers/char/lrng/lrng_jent.c
@@ -0,0 +1,89 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG Fast Noise Source: Jitter RNG
+ *
+ * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/types.h>
+#include <crypto/internal/jitterentropy.h>
+
+#include "lrng_internal.h"
+
+/*
+ * Estimated entropy of data is a 16th of LRNG_DRNG_SECURITY_STRENGTH_BITS.
+ * Albeit a full entropy assessment is provided for the noise source indicating
+ * that it provides high entropy rates and considering that it deactivates
+ * when it detects insufficient hardware, the chosen under estimation of
+ * entropy is considered to be acceptable to all reviewers.
+ */
+static u32 jitterrng = LRNG_DRNG_SECURITY_STRENGTH_BITS>>4;
+module_param(jitterrng, uint, 0644);
+MODULE_PARM_DESC(jitterrng, "Entropy in bits of 256 data bits from Jitter "
+			    "RNG noise source");
+
+/**
+ * lrng_get_jent() - Get Jitter RNG entropy
+ *
+ * @outbuf: buffer to store entropy
+ * @outbuflen: length of buffer
+ *
+ * Return:
+ * * > 0 on success where value provides the added entropy in bits
+ * * 0 if no fast source was available
+ */
+static struct rand_data *lrng_jent_state;
+
+u32 lrng_get_jent(u8 *outbuf, unsigned int outbuflen)
+{
+	int ret;
+	u32 ent_bits = jitterrng;
+	unsigned long flags;
+	static DEFINE_SPINLOCK(lrng_jent_lock);
+	static int lrng_jent_initialized = 0;
+
+	spin_lock_irqsave(&lrng_jent_lock, flags);
+
+	if (!ent_bits || (lrng_jent_initialized == -1)) {
+		spin_unlock_irqrestore(&lrng_jent_lock, flags);
+		return 0;
+	}
+
+	if (!lrng_jent_initialized) {
+		lrng_jent_state = jent_lrng_entropy_collector();
+		if (!lrng_jent_state) {
+			jitterrng = 0;
+			lrng_jent_initialized = -1;
+			spin_unlock_irqrestore(&lrng_jent_lock, flags);
+			pr_info("Jitter RNG unusable on current system\n");
+			return 0;
+		}
+		lrng_jent_initialized = 1;
+		pr_debug("Jitter RNG working on current system\n");
+	}
+	ret = jent_read_entropy(lrng_jent_state, outbuf, outbuflen);
+	spin_unlock_irqrestore(&lrng_jent_lock, flags);
+
+	if (ret) {
+		pr_debug("Jitter RNG failed with %d\n", ret);
+		return 0;
+	}
+
+	/* Obtain entropy statement */
+	if (outbuflen != LRNG_DRNG_SECURITY_STRENGTH_BYTES)
+		ent_bits = (ent_bits * outbuflen<<3) /
+			   LRNG_DRNG_SECURITY_STRENGTH_BITS;
+	/* Cap entropy to buffer size in bits */
+	ent_bits = min_t(u32, ent_bits, outbuflen<<3);
+	pr_debug("obtained %u bits of entropy from Jitter RNG noise source\n",
+		 ent_bits);
+
+	return ent_bits;
+}
+
+u32 lrng_jent_entropylevel(void)
+{
+	return min_t(u32, jitterrng, LRNG_DRNG_SECURITY_STRENGTH_BITS);
+}
-- 
2.24.1





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v28 10/12] LRNG - add SP800-90B compliant health tests
  2020-01-15 10:31       ` [PATCH v28 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                           ` (8 preceding siblings ...)
  2020-01-15 10:34         ` [PATCH v28 09/12] LRNG - add Jitter RNG fast noise source Stephan Müller
@ 2020-01-15 10:35         ` Stephan Müller
  2020-01-15 10:35         ` [PATCH v28 11/12] LRNG - add interface for gathering of raw entropy Stephan Müller
                           ` (2 subsequent siblings)
  12 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2020-01-15 10:35 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap, Julia Lawall, Dan Carpenter

Implement health tests for LRNG's slow noise sources as mandated by
SP-800-90B The file contains the following health tests:

- stuck test: The stuck test calculates the first, second and third
  discrete derivative of the time stamp to be processed by the LFSR.
  Only if all three values are non-zero, the received time delta is
  considered to be non-stuck.

- SP800-90B Repetition Count Test (RCT): The LRNG uses an enhanced
  version of the RCT specified in SP800-90B section 4.4.1. Instead of
  counting identical back-to-back values, the input to the RCT is the
  counting of the stuck values during the processing of received
  interrupt events. The RCT is applied with alpha=2^-30 compliant to
  the recommendation of FIPS 140-2 IG 9.8. During the counting operation,
  the LRNG always calculates the RCT cut-off value of C. If that value
  exceeds the allowed cut-off value, the LRNG will trigger the health
  test failure discussed below. An error is logged to the kernel log
  that such RCT failure occurred. This test is only applied and
  enforced in FIPS mode, i.e. when the kernel compiled with
  CONFIG_CONFIG_FIPS is started with fips=1.

- SP800-90B Adaptive Proportion Test (APT): The LRNG implements the
  APT as defined in SP800-90B section 4.4.2. The applied significance
  level again is alpha=2^-30 compliant to the recommendation of FIPS
  140-2 IG 9.8.

The aforementioned health tests are applied to the first 1,024 time stamps
obtained from interrupt events. In case one error is identified for either
the RCT, or the APT, the collected entropy is invalidated and the
SP800-90B startup health test is restarted.

As long as the SP800-90B startup health test is not completed, all LRNG
random number output interfaces that may block will block and not generate
any data. This implies that only those potentially blocking interfaces are
defined to provide random numbers that are seeded with the interrupt noise
source being SP800-90B compliant. All other output interfaces will not be
affected by the SP800-90B startup test and thus are not considered
SP800-90B compliant.

At runtime, the SP800-90B APT and RCT are applied to each time stamp
generated for a received interrupt. When either the APT and RCT indicates
a noise source failure, the LRNG is reset to a state it has immediately
after boot:

- all entropy counters are set to zero

- the SP800-90B startup tests are re-performed which implies that
getrandom(2) would block again until new entropy was collected

To summarize, the following rules apply:

• SP800-90B compliant output interfaces

  - /dev/random

  - getrandom(2) system call

  -  get_random_bytes kernel-internal interface when being triggered by
     the callback registered with add_random_ready_callback

• SP800-90B non-compliant output interfaces

  - /dev/urandom

  - get_random_bytes kernel-internal interface called directly

  - randomize_page kernel-internal interface

  - get_random_u32 and get_random_u64 kernel-internal interfaces

  - get_random_u32_wait, get_random_u64_wait, get_random_int_wait, and
    get_random_long_wait kernel-internal interfaces

If either the RCT, or the APT health test fails irrespective whether
during initialization or runtime, the following actions occur:

  1. The entropy of the entire entropy pool is invalidated.

  2. All DRNGs are reset which imply that they are treated as being
     not seeded and require a reseed during next invocation.

  3. The SP800-90B startup health test are initiated with all
     implications of the startup tests. That implies that from that point
     on, new events must be observed and its entropy must be inserted into
     the entropy pool before random numbers are calculated from the
     entropy pool.

Further details on the SP800-90B compliance and the availability of all
test tools required to perform all tests mandated by SP800-90B are
provided at [1].

The entire health testing code is compile-time configurable.

The patch provides a CONFIG_BROKEN configuration of the APT / RCT cutoff
values which have a high likelihood to trigger the health test failure.
The BROKEN APT cutoff is set to the exact mean of the expected value if
the time stamps are equally distributed (512 time stamps divided by 16
possible values due to using the 4 LSB of the time stamp). The BROKEN
RCT cutoff value is set to 1 which is likely to be triggered during
regular operation.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Kconfig       |  56 +++++
 drivers/char/lrng/Makefile      |   1 +
 drivers/char/lrng/lrng_health.c | 409 ++++++++++++++++++++++++++++++++
 3 files changed, 466 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_health.c

diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
index 10b7cbdb8c8e..12b6b3439853 100644
--- a/drivers/char/lrng/Kconfig
+++ b/drivers/char/lrng/Kconfig
@@ -103,4 +103,60 @@ config LRNG_JENT
 	  time or at runtime with the lrng_base.jitterrng configuration
 	  variable.
 
+config LRNG_HEALTH_TESTS
+	bool "Enable noise source online health tests"
+	help
+	  The online health tests validate the noise source at
+	  runtime for fatal errors. These tests include SP800-90B
+	  compliant tests which are invoked if the system is booted
+	  with fips=1. In case of fatal errors during active
+	  SP800-90B tests, the issue is logged and the noise
+	  data is discarded. These tests are required for full
+	  compliance with SP800-90B.
+
+	  If unsure, say Y.
+
+config LRNG_RCT_BROKEN
+	bool "SP800-90B RCT with dangerous low cutoff value"
+	depends on LRNG_HEALTH_TESTS
+	depends on BROKEN
+	default n
+	help
+	  This option enables a dangerously low SP800-90B repetitive
+	  count test (RCT) cutoff value which makes it very likely
+	  that the RCT is triggered to raise a self test failure.
+
+	  This option is ONLY intended for developers wanting to
+	  test the effectiveness of the SP800-90B RCT health test.
+
+	  If unsure, say N.
+
+config LRNG_APT_BROKEN
+	bool "SP800-90B APT with dangerous low cutoff value"
+	depends on LRNG_HEALTH_TESTS
+	depends on BROKEN
+	default n
+	help
+	  This option enables a dangerously low SP800-90B adaptive
+	  proportion test (APT) cutoff value which makes it very
+	  likely that the RCT is triggered to raise a self test
+	  failure.
+
+	  This option is ONLY intended for developers wanting to
+	  test the effectiveness of the SP800-90B APT health test.
+
+	  If unsure, say N.
+
+# Default taken from SP800-90B sec 4.4.1 - significance level 2^-30
+config LRNG_RCT_CUTOFF
+	int
+	default 31 if !LRNG_RCT_BROKEN
+	default 1 if LRNG_RCT_BROKEN
+
+# Default taken from SP800-90B sec 4.4.2 - significance level 2^-30
+config LRNG_APT_CUTOFF
+	int
+	default 325 if !LRNG_APT_BROKEN
+	default 32 if LRNG_APT_BROKEN
+
 endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index 4f5b6f38f0c4..c3008763dd14 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -14,3 +14,4 @@ obj-$(CONFIG_LRNG_DRNG_SWITCH)	+= lrng_switch.o
 obj-$(CONFIG_LRNG_DRBG)		+= lrng_drbg.o
 obj-$(CONFIG_LRNG_KCAPI)	+= lrng_kcapi.o
 obj-$(CONFIG_LRNG_JENT)		+= lrng_jent.o
+obj-$(CONFIG_LRNG_HEALTH_TESTS)	+= lrng_health.o
diff --git a/drivers/char/lrng/lrng_health.c b/drivers/char/lrng/lrng_health.c
new file mode 100644
index 000000000000..4aeca29d0b87
--- /dev/null
+++ b/drivers/char/lrng/lrng_health.c
@@ -0,0 +1,409 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * Linux Random Number Generator (LRNG) Health Testing
+ *
+ * Copyright (C) 2019 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/fips.h>
+#include <linux/module.h>
+
+#include "lrng_internal.h"
+
+/* Stuck Test */
+struct lrng_stuck_test {
+	u32 last_time;		/* Stuck test: time of previous IRQ */
+	u32 last_delta;		/* Stuck test: delta of previous IRQ */
+	u32 last_delta2;	/* Stuck test: 2. time derivation of prev IRQ */
+};
+
+/* Repetition Count Test */
+struct lrng_rct {
+	atomic_t rct_count;	/* Number of stuck values */
+};
+
+/* Adaptive Proportion Test */
+struct lrng_apt {
+	/* Data window size */
+#define LRNG_APT_WINDOW_SIZE	512
+	/* LSB of time stamp to process */
+#define LRNG_APT_LSB		16
+#define LRNG_APT_WORD_MASK	(LRNG_APT_LSB - 1)
+	atomic_t apt_count;		/* APT counter */
+	atomic_t apt_base;		/* APT base reference */
+
+	atomic_t apt_trigger;
+	bool apt_base_set;	/* Is APT base set? */
+};
+
+/* The health test code must operate lock-less */
+struct lrng_health {
+	struct lrng_rct rct;
+	struct lrng_apt apt;
+
+	bool health_test_enabled;
+
+	/* SP800-90B startup health tests */
+#define LRNG_SP80090B_STARTUP_SAMPLES  1024
+#define LRNG_SP80090B_STARTUP_BLOCKS   ((LRNG_SP80090B_STARTUP_SAMPLES + \
+					 LRNG_APT_WINDOW_SIZE - 1) /    \
+					LRNG_APT_WINDOW_SIZE)
+	bool sp80090b_startup_done;
+	atomic_t sp80090b_startup_blocks;
+};
+
+static struct lrng_health lrng_health = {
+	.rct.rct_count = ATOMIC_INIT(0),
+
+	.apt.apt_count = ATOMIC_INIT(0),
+	.apt.apt_base = ATOMIC_INIT(-1),
+	.apt.apt_trigger = ATOMIC_INIT(LRNG_APT_WINDOW_SIZE),
+	.apt.apt_base_set = false,
+
+	.health_test_enabled = true,
+
+	.sp80090b_startup_blocks = ATOMIC_INIT(LRNG_SP80090B_STARTUP_BLOCKS),
+	.sp80090b_startup_done = false,
+};
+
+static DEFINE_PER_CPU(struct lrng_stuck_test, lrng_stuck_test);
+
+static inline bool lrng_sp80090b_health_requested(void)
+{
+	/* Health tests are only requested in FIPS mode */
+	return fips_enabled;
+}
+
+static inline bool lrng_sp80090b_health_enabled(void)
+{
+	struct lrng_health *health = &lrng_health;
+
+	return lrng_sp80090b_health_requested() && health->health_test_enabled;
+}
+
+/***************************************************************************
+ * SP800-90B Compliance
+ *
+ * If the Linux-RNG is booted into FIPS mode, the following interfaces
+ * provide an SP800-90B compliant noise source:
+ *
+ * * /dev/random
+ * * getrandom(2)
+ * * get_random_bytes when using it in conjunction with
+ *   add_random_ready_callback
+ *
+ * All other interfaces, including /dev/urandom or get_random_bytes without
+ * the add_random_ready_callback cannot claim to use an SP800-90B compliant
+ * noise source.
+ ***************************************************************************/
+
+/*
+ * Perform SP800-90B startup testing
+ */
+static inline void lrng_sp80090b_startup(struct lrng_health *health)
+{
+	if (!health->sp80090b_startup_done &&
+	    atomic_dec_and_test(&health->sp80090b_startup_blocks)) {
+		health->sp80090b_startup_done = true;
+		pr_info("SP800-90B startup health tests completed\n");
+		lrng_init_ops(0);
+
+		/*
+		 * Force a reseed of DRNGs to ensure they are seeded with
+		 * entropy that passed the SP800-90B health tests.
+		 * As the DRNG always will reseed before generating
+		 * random numbers, it does not need a reseed trigger.
+		 */
+		lrng_drng_force_reseed();
+	}
+}
+
+/*
+ * Handle failure of SP800-90B startup testing
+ */
+static inline void lrng_sp80090b_startup_failure(struct lrng_health *health)
+{
+	/* Reset of LRNG and its entropy - NOTE: we are in atomic context */
+	lrng_reset();
+
+	/*
+	 * Reset the SP800-90B startup test.
+	 *
+	 * NOTE SP800-90B section 4.3 bullet 4 does not specify what
+	 * exactly is to be done in case of failure! Thus, we do what
+	 * makes sense, i.e. restarting the health test and thus gating
+	 * the output function of /dev/random and getrandom(2).
+	 */
+	atomic_set(&health->sp80090b_startup_blocks,
+		   LRNG_SP80090B_STARTUP_BLOCKS);
+}
+
+/*
+ * Handle failure of SP800-90B runtime testing
+ */
+static inline void lrng_sp80090b_runtime_failure(struct lrng_health *health)
+{
+	lrng_sp80090b_startup_failure(health);
+	health->sp80090b_startup_done = false;
+}
+
+static inline void lrng_sp80090b_failure(struct lrng_health *health)
+{
+	if (health->sp80090b_startup_done) {
+		pr_err("SP800-90B runtime health test failure - invalidating "
+		       "all existing entropy and initiate SP800-90B startup\n");
+		lrng_sp80090b_runtime_failure(health);
+	} else {
+		pr_err("SP800-90B startup test failure - resetting\n");
+		lrng_sp80090b_startup_failure(health);
+	}
+}
+
+/*
+ * Is the SP800-90B startup testing complete?
+ *
+ * This function is called by the LRNG to determine whether to unblock
+ * a certain user interface. Therefore, only the potentially blocking
+ * user interfaces are considered SP800-90B compliant.
+ */
+bool lrng_sp80090b_startup_complete(void)
+{
+	struct lrng_health *health = &lrng_health;
+
+	return (lrng_sp80090b_health_enabled()) ? health->sp80090b_startup_done:
+						  true;
+}
+
+bool lrng_sp80090b_compliant(void)
+{
+	struct lrng_health *health = &lrng_health;
+
+	return lrng_sp80090b_health_enabled() && health->sp80090b_startup_done;
+}
+
+/***************************************************************************
+ * Adaptive Proportion Test
+ *
+ * This test complies with SP800-90B section 4.4.2.
+ ***************************************************************************/
+
+/*
+ * Reset the APT counter
+ *
+ * @health [in] Reference to health state
+ */
+static inline void lrng_apt_reset(struct lrng_health *health,
+				  unsigned int time_masked)
+{
+	struct lrng_apt *apt = &health->apt;
+
+	pr_debug("APT value %d for base %d\n",
+		 atomic_read(&apt->apt_count), atomic_read(&apt->apt_base));
+
+	/* Reset APT */
+	atomic_set(&apt->apt_count, 0);
+	atomic_set(&apt->apt_base, time_masked);
+}
+
+static inline void lrng_apt_restart(struct lrng_health *health)
+{
+	struct lrng_apt *apt = &health->apt;
+
+	atomic_set(&apt->apt_trigger, LRNG_APT_WINDOW_SIZE);
+}
+
+/*
+ * Insert a new entropy event into APT
+ *
+ * This function does is void as it does not decide about the fate of a time
+ * stamp. An APT failure can only happen at the same time of a stuck test
+ * failure. Thus, the stuck failure will already decide how the time stamp
+ * is handled.
+ *
+ * @health [in] Reference to health state
+ * @now_time [in] Time stamp to process
+ */
+static inline void lrng_apt_insert(struct lrng_health *health,
+				   unsigned int now_time)
+{
+	struct lrng_apt *apt = &health->apt;
+
+	if (!lrng_sp80090b_health_requested())
+		return;
+
+	now_time &= LRNG_APT_WORD_MASK;
+
+	/* Initialization of APT */
+	if (!apt->apt_base_set) {
+		atomic_set(&apt->apt_base, now_time);
+		apt->apt_base_set = true;
+		return;
+	}
+
+	if (now_time == (unsigned int)atomic_read(&apt->apt_base)) {
+		u32 apt_val = (u32)atomic_inc_return_relaxed(&apt->apt_count);
+
+		if (apt_val >= CONFIG_LRNG_APT_CUTOFF)
+			lrng_sp80090b_failure(health);
+	}
+
+	if (atomic_dec_and_test(&apt->apt_trigger)) {
+		lrng_apt_restart(health);
+		lrng_apt_reset(health, now_time);
+		lrng_sp80090b_startup(health);
+	}
+}
+
+/***************************************************************************
+ * Repetition Count Test
+ *
+ * The LRNG uses an enhanced version of the Repetition Count Test
+ * (RCT) specified in SP800-90B section 4.4.1. Instead of counting identical
+ * back-to-back values, the input to the RCT is the counting of the stuck
+ * values while filling the entropy pool.
+ *
+ * The RCT is applied with an alpha of 2^-30 compliant to FIPS 140-2 IG 9.8.
+ *
+ * During the counting operation, the LRNG always calculates the RCT
+ * cut-off value of C. If that value exceeds the allowed cut-off value,
+ * the LRNG will invalidate all entropy for the entropy pool which implies
+ * that no data can be extracted from the entropy pool unless new entropy
+ * is received.
+ ***************************************************************************/
+
+/*
+ * Hot code path - Insert data for Repetition Count Test
+ *
+ * @health: Reference to health information
+ * @stuck: Decision of stuck test
+ */
+static inline void lrng_rct(struct lrng_health *health, int stuck)
+{
+	struct lrng_rct *rct = &health->rct;
+
+	if (!lrng_sp80090b_health_requested())
+		return;
+
+	if (stuck) {
+		u32 rct_count = atomic_add_return_relaxed(1, &rct->rct_count);
+
+		pr_debug("RCT count: %u\n", rct_count);
+
+		/*
+		 * The cutoff value is based on the following consideration:
+		 * alpha = 2^-30 as recommended in FIPS 140-2 IG 9.8.
+		 * In addition, we imply an entropy value H of 1 bit as this
+		 * is the minimum entropy required to provide full entropy.
+		 *
+		 * Note, rct_count (which equals to value B in the
+		 * pseudo code of SP800-90B section 4.4.1) starts with zero.
+		 * Hence we need to subtract one from the cutoff value as
+		 * calculated following SP800-90B.
+		 */
+		if (rct_count >= CONFIG_LRNG_RCT_CUTOFF) {
+			atomic_set(&rct->rct_count, 0);
+
+			/*
+			 * APT must start anew as we consider all previously
+			 * recorded data to contain no entropy.
+			 */
+			lrng_apt_restart(health);
+
+			lrng_sp80090b_failure(health);
+		}
+	} else {
+		atomic_set(&rct->rct_count, 0);
+	}
+}
+
+/***************************************************************************
+ * Stuck Test
+ *
+ * Checking the:
+ *      1st derivative of the event occurrence (time delta)
+ *      2nd derivative of the event occurrence (delta of time deltas)
+ *      3rd derivative of the event occurrence (delta of delta of time deltas)
+ *
+ * All values must always be non-zero. The stuck test is only valid disabled if
+ * high-resolution time stamps are identified after initialization.
+ ***************************************************************************/
+
+static inline u32 lrng_delta(u32 prev, u32 next)
+{
+	/*
+	 * Note that this (unsigned) subtraction does yield the correct value
+	 * in the wraparound-case, i.e. when next < prev.
+	 */
+	return (next - prev);
+}
+
+/*
+ * Hot code path
+ *
+ * @health: Reference to health information
+ * @now: Event time
+ * @return: 0 event occurrence not stuck (good time stamp)
+ *	    != 0 event occurrence stuck (reject time stamp)
+ */
+static inline int lrng_irq_stuck(struct lrng_stuck_test *stuck, u32 now_time)
+{
+	u32 delta = lrng_delta(stuck->last_time, now_time);
+	u32 delta2 = lrng_delta(stuck->last_delta, delta);
+	u32 delta3 = lrng_delta(stuck->last_delta2, delta2);
+
+	stuck->last_time = now_time;
+	stuck->last_delta = delta;
+	stuck->last_delta2 = delta2;
+
+	if (!delta || !delta2 || !delta3)
+		return 1;
+
+	return 0;
+}
+
+/***************************************************************************
+ * Health test interfaces
+ ***************************************************************************/
+
+/*
+ * Disable all health tests
+ */
+void lrng_health_disable(void)
+{
+	struct lrng_health *health = &lrng_health;
+
+	health->health_test_enabled = false;
+
+	if (lrng_sp80090b_health_requested())
+		pr_warn("SP800-90B compliance requested but the Linux RNG is "
+			"NOT SP800-90B compliant\n");
+}
+
+/*
+ * Hot code path - Perform health test on time stamp received from an event
+ *
+ * @now_time Time stap
+ */
+enum lrng_health_res lrng_health_test(u32 now_time)
+{
+	struct lrng_health *health = &lrng_health;
+	struct lrng_stuck_test *stuck_test = this_cpu_ptr(&lrng_stuck_test);
+	int stuck;
+
+	if (!health->health_test_enabled)
+		return lrng_health_pass;
+
+	lrng_apt_insert(health, now_time);
+
+	stuck = lrng_irq_stuck(stuck_test, now_time);
+	lrng_rct(health, stuck);
+	if (stuck) {
+		/* SP800-90B disallows using a failing health test time stamp */
+		return lrng_sp80090b_health_requested() ?
+			lrng_health_fail_drop : lrng_health_fail_use;
+	}
+
+	return lrng_health_pass;
+}
-- 
2.24.1





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v28 11/12] LRNG - add interface for gathering of raw entropy
  2020-01-15 10:31       ` [PATCH v28 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                           ` (9 preceding siblings ...)
  2020-01-15 10:35         ` [PATCH v28 10/12] LRNG - add SP800-90B compliant health tests Stephan Müller
@ 2020-01-15 10:35         ` Stephan Müller
  2020-01-16  0:18           ` Randy Dunlap
  2020-01-15 10:36         ` [PATCH v28 12/12] LRNG - add power-on and runtime self-tests Stephan Müller
  2020-01-19 21:12         ` [PATCH v29 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
  12 siblings, 1 reply; 162+ messages in thread
From: Stephan Müller @ 2020-01-15 10:35 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap, Julia Lawall, Dan Carpenter

The test interface allows a privileged process to capture the raw
unconditioned noise that is collected by the LRNG for statistical
analysis. Such testing allows the analysis how much entropy
the interrupt noise source provides on a given platform.
Extracted noise data is not used to seed the LRNG. This
is a test interface and not appropriate for production systems.
Yet, the interface is considered to be sufficiently secured for
production systems.

Access to the data is given through the lrng_raw debugfs file. The
data buffer should be multiples of sizeof(u32) to fill the entire
buffer. Using the option lrng_testing.boot_test=1 the raw noise of
the first 1000 entropy events since boot can be sampled.

This test interface allows generating the data required for
analysis whether the LRNG is in compliance with SP800-90B
sections 3.1.3 and 3.1.4.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Kconfig        |  16 ++
 drivers/char/lrng/Makefile       |   1 +
 drivers/char/lrng/lrng_testing.c | 271 +++++++++++++++++++++++++++++++
 3 files changed, 288 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_testing.c

diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
index 12b6b3439853..e503a4bb7475 100644
--- a/drivers/char/lrng/Kconfig
+++ b/drivers/char/lrng/Kconfig
@@ -159,4 +159,20 @@ config LRNG_APT_CUTOFF
 	default 325 if !LRNG_APT_BROKEN
 	default 32 if LRNG_APT_BROKEN
 
+config LRNG_TESTING
+	bool "Enable entropy test interface to LRNG noise source"
+	depends on DEBUG_FS
+	help
+	  The test interface allows a privileged process to capture
+	  the raw unconditioned noise that is collected by the LRNG
+	  for statistical analysis. Extracted noise data is not used
+	  to seed the LRNG.
+
+	  The raw noise data can be obtained using the lrng_raw
+	  debugfs file. Using the option lrng_testing.boot_test=1
+	  the raw noise of the first 1000 entropy events since boot
+	  can be sampled.
+
+	  If unsure, say N.
+
 endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index c3008763dd14..b2ce1979dc4b 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -15,3 +15,4 @@ obj-$(CONFIG_LRNG_DRBG)		+= lrng_drbg.o
 obj-$(CONFIG_LRNG_KCAPI)	+= lrng_kcapi.o
 obj-$(CONFIG_LRNG_JENT)		+= lrng_jent.o
 obj-$(CONFIG_LRNG_HEALTH_TESTS)	+= lrng_health.o
+obj-$(CONFIG_LRNG_TESTING)	+= lrng_testing.o
diff --git a/drivers/char/lrng/lrng_testing.c b/drivers/char/lrng/lrng_testing.c
new file mode 100644
index 000000000000..0e287eccd622
--- /dev/null
+++ b/drivers/char/lrng/lrng_testing.c
@@ -0,0 +1,271 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * Linux Random Number Generator (LRNG) Raw entropy collection tool
+ *
+ * Copyright (C) 2019 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/atomic.h>
+#include <linux/bug.h>
+#include <linux/debugfs.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/sched/signal.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+#include <linux/workqueue.h>
+#include <asm/errno.h>
+
+#include "lrng_internal.h"
+
+#define LRNG_TESTING_RINGBUFFER_SIZE	1024
+#define LRNG_TESTING_RINGBUFFER_MASK	(LRNG_TESTING_RINGBUFFER_SIZE - 1)
+
+static u32 lrng_testing_rb[LRNG_TESTING_RINGBUFFER_SIZE];
+static u32 lrng_rb_reader = 0;
+static u32 lrng_rb_writer = 0;
+static atomic_t lrng_testing_enabled = ATOMIC_INIT(0);
+
+static DECLARE_WAIT_QUEUE_HEAD(lrng_raw_read_wait);
+static DEFINE_SPINLOCK(lrng_raw_lock);
+
+/*
+ * 0 ==> No boot test, gathering of runtime data allowed
+ * 1 ==> Boot test enabled and ready for collecting data, gathering runtime
+ *	 data is disabled
+ * 2 ==> Boot test completed and disabled, gathering of runtime data is
+ *	 disabled
+ */
+static u32 boot_test = 0;
+module_param(boot_test, uint, 0644);
+MODULE_PARM_DESC(boot_test, "Enable gathering boot time entropy of the first"
+			    " entropy events");
+
+static inline void lrng_raw_entropy_reset(void)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&lrng_raw_lock, flags);
+	lrng_rb_reader = 0;
+	lrng_rb_writer = 0;
+	spin_unlock_irqrestore(&lrng_raw_lock, flags);
+}
+
+static void lrng_raw_entropy_init(void)
+{
+	/*
+	 * The boot time testing implies we have a running test. If the
+	 * caller wants to clear it, he has to unset the boot_test flag
+	 * at runtime via sysfs to enable regular runtime testing
+	 */
+	if (boot_test)
+		return;
+
+	lrng_raw_entropy_reset();
+	atomic_set(&lrng_testing_enabled, 1);
+	pr_warn("Enabling raw entropy collection\n");
+}
+
+static void lrng_raw_entropy_fini(void)
+{
+	if (boot_test)
+		return;
+
+	atomic_set(&lrng_testing_enabled, 0);
+	lrng_raw_entropy_reset();
+	pr_warn("Disabling raw entropy collection\n");
+}
+
+bool lrng_raw_entropy_store(u32 value)
+{
+	unsigned long flags;
+
+	if (!atomic_read(&lrng_testing_enabled) && (boot_test != 1))
+		return false;
+
+	spin_lock_irqsave(&lrng_raw_lock, flags);
+
+	/*
+	 * Disable entropy testing for boot time testing after ring buffer
+	 * is filled.
+	 */
+	if (boot_test) {
+		if (lrng_rb_writer > LRNG_TESTING_RINGBUFFER_SIZE) {
+			boot_test = 2;
+			pr_warn_once("Boot time entropy collection test "
+				     "disabled\n");
+			spin_unlock_irqrestore(&lrng_raw_lock, flags);
+			return false;
+		}
+
+		if (lrng_rb_writer == 1)
+			pr_warn("Boot time entropy collection test enabled\n");
+	}
+
+	lrng_testing_rb[lrng_rb_writer & LRNG_TESTING_RINGBUFFER_MASK] = value;
+	lrng_rb_writer++;
+
+	spin_unlock_irqrestore(&lrng_raw_lock, flags);
+
+	if (wq_has_sleeper(&lrng_raw_read_wait))
+		wake_up_interruptible(&lrng_raw_read_wait);
+
+	return true;
+}
+
+static inline bool lrng_raw_have_data(void)
+{
+	return ((lrng_rb_writer & LRNG_TESTING_RINGBUFFER_MASK) !=
+		 (lrng_rb_reader & LRNG_TESTING_RINGBUFFER_MASK));
+}
+
+static int lrng_raw_entropy_reader(u8 *outbuf, u32 outbuflen)
+{
+	unsigned long flags;
+	int collected_data = 0;
+
+	lrng_raw_entropy_init();
+
+	while (outbuflen) {
+		spin_lock_irqsave(&lrng_raw_lock, flags);
+
+		/* We have no data or reached the writer. */
+		if (!lrng_rb_writer || (lrng_rb_writer == lrng_rb_reader)) {
+
+			spin_unlock_irqrestore(&lrng_raw_lock, flags);
+
+			/*
+			 * Now we gathered all boot data, enable regular data
+			 * collection.
+			 */
+			if (boot_test) {
+				boot_test = 0;
+				goto out;
+			}
+
+			wait_event_interruptible(lrng_raw_read_wait,
+						 lrng_raw_have_data());
+			if (signal_pending(current)) {
+				collected_data = -ERESTARTSYS;
+				goto out;
+			}
+
+			continue;
+		}
+
+		/* We copy out word-wise */
+		if (outbuflen < sizeof(u32)) {
+			spin_unlock_irqrestore(&lrng_raw_lock, flags);
+			goto out;
+		}
+
+		memcpy(outbuf, &lrng_testing_rb[lrng_rb_reader], sizeof(u32));
+		lrng_rb_reader++;
+
+		spin_unlock_irqrestore(&lrng_raw_lock, flags);
+
+		outbuf += sizeof(u32);
+		outbuflen -= sizeof(u32);
+		collected_data += sizeof(u32);
+	}
+
+out:
+	lrng_raw_entropy_fini();
+	return collected_data;
+}
+
+/**************************************************************************
+ * Debugfs interface
+ **************************************************************************/
+static int lrng_raw_extract_user(char __user *buf, size_t nbytes)
+{
+	u8 *tmp, *tmp_aligned;
+	int ret = 0, large_request = (nbytes > 256);
+
+	/*
+	 * The intention of this interface is for collecting at least
+	 * 1000 samples due to the SP800-90B requirements. So, we make no
+	 * effort in avoiding allocating more memory that actually needed
+	 * by the user. Hence, we allocate sufficient memory to always hold
+	 * that amount of data.
+	 */
+	tmp = kmalloc(LRNG_TESTING_RINGBUFFER_SIZE + sizeof(u32), GFP_KERNEL);
+	if (!tmp)
+		return -ENOMEM;
+
+	tmp_aligned = PTR_ALIGN(tmp, sizeof(u32));
+
+	while (nbytes) {
+		int i;
+
+		if (large_request && need_resched()) {
+			if (signal_pending(current)) {
+				if (ret == 0)
+					ret = -ERESTARTSYS;
+				break;
+			}
+			schedule();
+		}
+
+		i = min_t(int, nbytes, LRNG_TESTING_RINGBUFFER_SIZE);
+		i = lrng_raw_entropy_reader(tmp_aligned, i);
+		if (i <= 0) {
+			if (i < 0)
+				ret = i;
+			break;
+		}
+		if (copy_to_user(buf, tmp_aligned, i)) {
+			ret = -EFAULT;
+			break;
+		}
+
+		nbytes -= i;
+		buf += i;
+		ret += i;
+	}
+
+	kzfree(tmp);
+	return ret;
+}
+
+/* DebugFS operations and definition of the debugfs files */
+static ssize_t lrng_raw_read(struct file *file, char __user *to,
+			     size_t count, loff_t *ppos)
+{
+	loff_t pos = *ppos;
+	int ret;
+
+	if (!count)
+		return 0;
+
+	ret = lrng_raw_extract_user(to, count);
+	if (ret < 0)
+		return ret;
+
+	count -= ret;
+	*ppos = pos + count;
+
+	return ret;
+}
+
+static const struct file_operations lrng_raw_name_fops = {
+	.owner = THIS_MODULE,
+	.read = lrng_raw_read,
+};
+
+static int __init lrng_raw_init(void)
+{
+	struct dentry *lrng_raw_debugfs_root;
+
+	lrng_raw_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL);
+	debugfs_create_file_unsafe("lrng_raw", 0400, lrng_raw_debugfs_root,
+				   NULL, &lrng_raw_name_fops);
+
+	return 0;
+}
+
+module_init(lrng_raw_init);
-- 
2.24.1





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v28 12/12] LRNG - add power-on and runtime self-tests
  2020-01-15 10:31       ` [PATCH v28 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                           ` (10 preceding siblings ...)
  2020-01-15 10:35         ` [PATCH v28 11/12] LRNG - add interface for gathering of raw entropy Stephan Müller
@ 2020-01-15 10:36         ` Stephan Müller
  2020-01-19 21:12         ` [PATCH v29 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
  12 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2020-01-15 10:36 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap, Julia Lawall, Dan Carpenter

Parts of the LFSR are already covered by self-tests, including:

* Self-test of SP800-90A DRBG provided by the Linux kernel crypto API.

* Self-test of the PRNG provided by the Linux kernel crypto API.

* Raw noise source data testing including SP800-90B compliant
  tests when enabling CONFIG_LRNG_HEALTH_TESTS

This patch adds the self-tests for the remaining critical functions of
the LRNG that are essential to maintain entropy and provide
cryptographic strong random numbers. The following self-tests are
implemented:

* Self-test of the time array maintenance. This test verifies whether
the time stamp array management to store multiple values in one integer
implements a concatenation of the data.

* Self-test of the LFSR operation. This test injects a monotonic
increasing counter into the LFSR. After completion of the injection of
the counter, 3 pool words are compared with known good values. The known
good values are calculated with the newly-developed tool
lfsr_testvector_generation provided as part of the LRNG test tool set at
[1].

* Self-test of the Hash_DF operation ensures that this function operates
compliant to the specification. The self-test performs a Hash_DF
operation of a zeroized entropy pool state. The test vectors are
generated using the newly-developed tool hash_df_testvector_generation
provided as part of the LRNG test tool set at [1].

* Self-test of the ChaCha20 DRNG is based on the self-tests that are
already present and implemented with the stand-alone user space
ChaCha20 DRNG implementation available at [2]. The self-tests cover
different use cases of the DRNG seeded with known seed data.

The status of the LRNG self-tests is provided with the selftest_status
SysFS file. If the file contains a zero, the self-tests passed. The
value 0xffffffff means that the self-tests were not executed. Any other
value indicates a self-test failure.

The self-test may be compiled to panic the system if the self-test
fails.

All self-tests operate on private state data structures. This implies
that none of the self-tests have any impact on the regular LRNG
operations. This allows the self-tests to be repeated at runtime by
writing anything into the selftest_status SysFS file.

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

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
CC: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
CC: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Kconfig         |  25 ++
 drivers/char/lrng/Makefile        |   1 +
 drivers/char/lrng/lrng_selftest.c | 418 ++++++++++++++++++++++++++++++
 3 files changed, 444 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_selftest.c

diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
index e503a4bb7475..0c9ad9563fb7 100644
--- a/drivers/char/lrng/Kconfig
+++ b/drivers/char/lrng/Kconfig
@@ -175,4 +175,29 @@ config LRNG_TESTING
 
 	  If unsure, say N.
 
+config LRNG_SELFTEST
+	bool "Enable power-on and on-demand self-tests"
+	help
+	  The power-on self-tests are executed during boot time
+	  covering the ChaCha20 DRNG, the LFSR processing and the
+	  time stamp management of the LRNG.
+
+	  The on-demand self-tests are triggered by writing any
+	  value into the SysFS file selftest_status. At the same
+	  time, when reading this file, the test status is
+	  returned. A zero indicates that all tests were executed
+	  successfully.
+
+	  If unsure, say Y.
+
+if LRNG_SELFTEST
+
+config LRNG_SELFTEST_PANIC
+	bool "Panic the kernel upon self-test failure"
+	help
+	  If the option is enabled, the kernel is terminated if an
+	  LRNG power-on self-test failure is detected.
+
+endif # LRNG_SELFTEST
+
 endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index b2ce1979dc4b..92219c565f66 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -16,3 +16,4 @@ obj-$(CONFIG_LRNG_KCAPI)	+= lrng_kcapi.o
 obj-$(CONFIG_LRNG_JENT)		+= lrng_jent.o
 obj-$(CONFIG_LRNG_HEALTH_TESTS)	+= lrng_health.o
 obj-$(CONFIG_LRNG_TESTING)	+= lrng_testing.o
+obj-$(CONFIG_LRNG_SELFTEST)	+= lrng_selftest.o
diff --git a/drivers/char/lrng/lrng_selftest.c b/drivers/char/lrng/lrng_selftest.c
new file mode 100644
index 000000000000..da213572e1dd
--- /dev/null
+++ b/drivers/char/lrng/lrng_selftest.c
@@ -0,0 +1,418 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG power-on and on-demand self-test
+ *
+ * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+/*
+ * In addition to the self-tests below, the following LRNG components
+ * are covered with self-tests during regular operation:
+ *
+ * * power-on self-test: SP800-90A DRBG provided by the Linux kernel crypto API
+ * * power-on self-test: PRNG provided by the Linux kernel crypto API
+ * * runtime test: Raw noise source data testing including SP800-90B compliant
+ *		   tests when enabling CONFIG_LRNG_HEALTH_TESTS
+ *
+ * Additional developer tests present with LRNG code:
+ * * SP800-90B APT and RCT test enforcement validation when enabling
+ *   CONFIG_LRNG_APT_BROKEN or CONFIG_LRNG_RCT_BROKEN.
+ * * Collection of raw entropy from the interrupt noise source when enabling
+ *   CONFIG_LRNG_TESTING and pulling the data from the kernel with the provided
+ *   interface.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/lrng.h>
+#include <linux/slab.h>
+
+#include "lrng_chacha20.h"
+#include "lrng_internal.h"
+#include "lrng_lfsr.h"
+#include "lrng_sw_noise.h"
+
+#define LRNG_SELFTEST_PASSED		0
+#define LRNG_SEFLTEST_ERROR_TIME	(1 << 0)
+#define LRNG_SEFLTEST_ERROR_LFSR	(1 << 1)
+#define LRNG_SEFLTEST_ERROR_CHACHA20	(1 << 2)
+#define LRNG_SEFLTEST_ERROR_HASHDF	(1 << 3)
+#define LRNG_SELFTEST_NOT_EXECUTED	0xffffffff
+
+static u32 lrng_time_selftest[LRNG_TIME_ARRAY_SIZE];
+
+static unsigned int lrng_selftest_status = LRNG_SELFTEST_NOT_EXECUTED;
+
+static inline void lrng_time_process_selftest_insert(u32 time)
+{
+	static u32 lrng_time_selftest_ptr = 0;
+	u32 ptr = lrng_time_selftest_ptr++ & LRNG_TIME_WORD_MASK;
+
+	lrng_time_selftest[lrng_time_idx2array(ptr)] |=
+		lrng_time_slot_val(time & LRNG_TIME_SLOTSIZE_MASK,
+				   lrng_time_idx2slot(ptr));
+}
+
+static unsigned int lrng_time_process_selftest(void)
+{
+	u32 time;
+	u32 idx_zero_compare = (0 << 0) | (1 << 8) | (2 << 16) | (3 << 24);
+	u32 idx_one_compare  = (4 << 0) | (5 << 8) | (6 << 16) | (7 << 24);
+	u32 idx_last_compare = ((LRNG_TIME_NUM_VALUES - 4) << 0)  |
+			       ((LRNG_TIME_NUM_VALUES - 3) << 8)  |
+			       ((LRNG_TIME_NUM_VALUES - 2) << 16) |
+			       ((LRNG_TIME_NUM_VALUES - 1) << 24);
+
+	(void)idx_one_compare;
+
+	for (time = 0; time < LRNG_TIME_NUM_VALUES; time++)
+		lrng_time_process_selftest_insert(time);
+
+	if ((lrng_time_selftest[0] != idx_zero_compare) ||
+#if (LRNG_TIME_ARRAY_SIZE > 1)
+	    (lrng_time_selftest[1] != idx_one_compare)  ||
+#endif
+	    (lrng_time_selftest[LRNG_TIME_ARRAY_SIZE - 1] != idx_last_compare))
+	{
+		pr_err("LRNG time array self-test FAILED\n");
+		return LRNG_SEFLTEST_ERROR_TIME;
+	}
+
+	return LRNG_SELFTEST_PASSED;
+}
+
+/*
+ * The test vectors are generated with the lfsr_testvector_generation tool
+ * provided as part of the test tool set of the LRNG.
+ */
+static unsigned int lrng_pool_lfsr_selftest(void)
+{
+	/*
+	 * First, 67th and last entry of entropy pool.
+	 *
+	 * The 67th entry is picked because this one is the first to receive
+	 * an entry. As we start with 1 to inject into the LFSR, the
+	 * 67th entry should be equal to rol(1, 7) >> 3 considering that
+	 * all other values of the LFSR are zero and the the twist value of 0
+	 * is applied.
+	 */
+	static u32 const lrng_lfsr_selftest_result[][3] = {
+		{ 0xf56df24a, 0x00000010, 0x0e014939 },
+		{ 0x4b130726, 0x00000010, 0x2802f509 },
+		{ 0x87279152, 0x00000010, 0x00150000 },
+		{ 0x0b67f997, 0x00000010, 0x00150000 },
+		{ 0x4fea174f, 0x00000010, 0xcbf4a6ae },
+		{ 0x77149108, 0x00000010, 0x77bfadf2 },
+		{ 0x1e96037e, 0x00000010, 0x18017e79 },
+		{ 0xc84acef2, 0x00000010, 0x6345f7a8 },
+		{ 0x6a2eb6df, 0x00000010, 0x03950000 },
+	};
+	struct lrng_pool *lrng_pool, *lrng_pool_aligned;
+	u32 i, ret = LRNG_SELFTEST_PASSED;
+
+	BUILD_BUG_ON(ARRAY_SIZE(lrng_lfsr_selftest_result) <
+							CONFIG_LRNG_POOL_SIZE);
+
+	lrng_pool = kzalloc(sizeof(struct lrng_pool) + LRNG_KCAPI_ALIGN,
+			    GFP_KERNEL);
+	if (!lrng_pool)
+		return LRNG_SEFLTEST_ERROR_LFSR;
+	lrng_pool_aligned = PTR_ALIGN(lrng_pool, sizeof(u32));
+
+	for (i = 1; i <= LRNG_POOL_SIZE; i++)
+		_lrng_pool_lfsr_u32(lrng_pool_aligned, i);
+
+	if ((atomic_read_u32(&lrng_pool_aligned->pool[0]) !=
+	     lrng_lfsr_selftest_result[CONFIG_LRNG_POOL_SIZE][0]) ||
+	    (atomic_read_u32(&lrng_pool_aligned->pool[67 &
+						      (LRNG_POOL_SIZE - 1)]) !=
+	     lrng_lfsr_selftest_result[CONFIG_LRNG_POOL_SIZE][1]) ||
+	    (atomic_read_u32(&lrng_pool_aligned->pool[LRNG_POOL_SIZE - 1]) !=
+	     lrng_lfsr_selftest_result[CONFIG_LRNG_POOL_SIZE][2])) {
+		pr_err("LRNG LFSR self-test FAILED\n");
+		ret = LRNG_SEFLTEST_ERROR_LFSR;
+	}
+
+	kfree(lrng_pool);
+	return ret;
+}
+
+/*
+ * The test vectors are generated with the hash_df_testvector_generation tool
+ * provided as part of the test tool set of the LRNG.
+ */
+static unsigned int lrng_hash_df_selftest(void)
+{
+	const struct lrng_crypto_cb *crypto_cb = &lrng_cc20_crypto_cb;
+
+	/*
+	 * The size of 45 bytes is chosen arbitrarily. Yet, this size should
+	 * ensure that we have at least two hash blocks plus some fraction
+	 * of a hash block generated.
+	 */
+	static u8 const lrng_hash_df_selftest_result[][45] = {
+		{
+			0x3b, 0xbe, 0x7a, 0xbd, 0x2b, 0x16, 0x02, 0x4c,
+			0xfc, 0xd3, 0x02, 0x15, 0xf0, 0x86, 0xd4, 0xdb,
+			0x49, 0xec, 0x26, 0x53, 0xd6, 0xc9, 0x6d, 0xad,
+			0x24, 0xca, 0x72, 0x89, 0x2c, 0xfa, 0x48, 0x18,
+			0xf7, 0x47, 0xb5, 0x2f, 0x92, 0xa2, 0x1b, 0xd9,
+			0x24, 0xa7, 0x2f, 0xa2, 0x0b,
+		}, {
+			0xd2, 0xaa, 0xf9, 0x76, 0x26, 0xc6, 0x13, 0xea,
+			0xb8, 0xde, 0xe6, 0x88, 0x8f, 0xc4, 0x7a, 0x7d,
+			0x9c, 0xb4, 0x1b, 0xd1, 0xd1, 0x8a, 0x40, 0xc9,
+			0xaa, 0x45, 0xa6, 0xb6, 0xb5, 0x6f, 0xf6, 0xbc,
+			0xbb, 0x77, 0x37, 0xbc, 0x5a, 0x2d, 0xcc, 0x84,
+			0x25, 0x68, 0x5e, 0xba, 0x16,
+		}, {
+			0x58, 0x66, 0x82, 0x88, 0x29, 0x19, 0xa4, 0xbb,
+			0x33, 0x42, 0xc9, 0x72, 0x0d, 0x68, 0x6e, 0xb9,
+			0xc6, 0xe0, 0x7a, 0xf9, 0x20, 0xca, 0x6d, 0x18,
+			0x35, 0xec, 0xfa, 0x9e, 0xf6, 0x3a, 0xa7, 0xb6,
+			0x92, 0x7a, 0xe5, 0xcd, 0xc5, 0x13, 0x9f, 0x65,
+			0x6a, 0xe1, 0xe4, 0x3f, 0xb9,
+		}, {
+			0xdd, 0xf1, 0x34, 0xca, 0x08, 0xe3, 0xce, 0x8a,
+			0x26, 0x6b, 0xce, 0x99, 0x8a, 0x84, 0xd2, 0x21,
+			0x98, 0x10, 0x95, 0x5f, 0x9f, 0xc3, 0xf2, 0xe4,
+			0x79, 0x75, 0xb5, 0x15, 0xa7, 0xa2, 0xf1, 0xc4,
+			0xdc, 0x67, 0xcb, 0x67, 0x8c, 0xb2, 0x1b, 0xd5,
+			0xd6, 0x8b, 0xc2, 0x34, 0xd6,
+		}, {
+			0xc3, 0x16, 0x9d, 0xf0, 0x78, 0x15, 0xab, 0xf2,
+			0x2f, 0xc9, 0x2e, 0xe1, 0xc6, 0x5e, 0xfa, 0x03,
+			0xaf, 0xd4, 0xd5, 0x47, 0x2a, 0xe8, 0x06, 0xe8,
+			0x7e, 0x0a, 0x71, 0xc7, 0x0d, 0x39, 0xb1, 0xa9,
+			0x5a, 0x49, 0xee, 0x8b, 0x2f, 0xcd, 0xea, 0x96,
+			0xcc, 0x08, 0x71, 0xef, 0x9c,
+		}, {
+			0x1a, 0x3d, 0x70, 0x39, 0xc2, 0x02, 0x4d, 0x3a,
+			0xaa, 0x14, 0x20, 0x88, 0x96, 0x4c, 0x7c, 0xe4,
+			0xaa, 0x49, 0x89, 0x30, 0x50, 0x96, 0xb6, 0xa7,
+			0x55, 0x0a, 0xf8, 0xd2, 0x4e, 0x83, 0x9d, 0x1f,
+			0x56, 0x49, 0x13, 0xc6, 0x46, 0x55, 0x73, 0x0d,
+			0x74, 0xcd, 0x81, 0xe0, 0x65,
+		}, {
+			0x4b, 0xf6, 0x49, 0x89, 0x2a, 0x9f, 0x67, 0xd7,
+			0xb8, 0x1d, 0xbb, 0x5d, 0xf0, 0x1b, 0x60, 0xb6,
+			0xb7, 0xf3, 0x86, 0x6d, 0xe0, 0x04, 0xa1, 0xbc,
+			0x3b, 0xb0, 0x10, 0x91, 0xe8, 0x22, 0x67, 0x5b,
+			0xe8, 0xf0, 0x4f, 0x82, 0x70, 0xc7, 0xe1, 0xc8,
+			0xd8, 0xad, 0x70, 0xcf, 0xf6,
+		}, {
+			0x60, 0x1f, 0x71, 0x07, 0x92, 0xae, 0xa0, 0x24,
+			0xb6, 0xa4, 0x10, 0x70, 0x1f, 0x94, 0x51, 0x9a,
+			0x5a, 0x81, 0xc4, 0x46, 0x78, 0x56, 0x71, 0xdd,
+			0x45, 0x63, 0x01, 0x34, 0x87, 0x79, 0xb4, 0xd5,
+			0x91, 0x79, 0xb9, 0x93, 0x11, 0x44, 0x50, 0xad,
+			0x64, 0x7e, 0x5c, 0xec, 0x16,
+		}, {
+			0x49, 0x2f, 0xa0, 0x45, 0xf8, 0xb0, 0x80, 0x88,
+			0x79, 0xeb, 0xb6, 0x82, 0x1c, 0xf3, 0x67, 0xc4,
+			0x88, 0x88, 0xe9, 0x75, 0x20, 0x54, 0x78, 0xc6,
+			0x5c, 0x59, 0xcf, 0xd9, 0x73, 0x12, 0x17, 0xf4,
+			0x30, 0x9c, 0xb7, 0x21, 0x45, 0xe2, 0xb6, 0x0c,
+			0x0c, 0xeb, 0x1b, 0xdc, 0xdc,
+		}
+	};
+	struct lrng_pool *lrng_pool, *lrng_pool_aligned;
+	u8 hash_df[sizeof(lrng_hash_df_selftest_result[0])]
+							__aligned(sizeof(u32));
+	u32 generated;
+	int ret = 0;
+
+	BUILD_BUG_ON(ARRAY_SIZE(lrng_hash_df_selftest_result) <
+							CONFIG_LRNG_POOL_SIZE);
+
+	lrng_pool = kzalloc(sizeof(struct lrng_pool) + LRNG_KCAPI_ALIGN,
+			    GFP_KERNEL);
+	if (!lrng_pool)
+		return LRNG_SEFLTEST_ERROR_HASHDF;
+	lrng_pool_aligned = PTR_ALIGN(lrng_pool, sizeof(u32));
+
+	generated = __lrng_pool_hash_df(crypto_cb, NULL, lrng_pool_aligned,
+					hash_df, sizeof(hash_df) << 3);
+
+	if ((generated >> 3) != sizeof(hash_df) ||
+	    memcmp(hash_df, lrng_hash_df_selftest_result[CONFIG_LRNG_POOL_SIZE],
+		   sizeof(hash_df))) {
+		pr_err("LRNG Hash DF self-test FAILED\n");
+		ret = LRNG_SEFLTEST_ERROR_HASHDF;
+	}
+
+	kfree(lrng_pool);
+	return ret;
+}
+
+/*
+ * The test vectors were generated using the ChaCha20 DRNG from
+ * https://www.chronox.de/chacha20.html
+ */
+static unsigned int lrng_chacha20_drng_selftest(void)
+{
+	const struct lrng_crypto_cb *crypto_cb = &lrng_cc20_crypto_cb;
+	static u8 const seed[CHACHA_KEY_SIZE * 2] = {
+		0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+		0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+		0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+		0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+		0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+		0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+		0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+		0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+	};
+	struct chacha20_block chacha20;
+	int ret;
+	u8 outbuf[CHACHA_KEY_SIZE * 2] __aligned(sizeof(u32));
+
+	/*
+	 * Expected result when ChaCha20 DRNG state is zero:
+	 *	* constants are set to "expand 32-byte k"
+	 *	* remaining state is 0
+	 * and pulling one half ChaCha20 DRNG block.
+	 */
+	static u8 const expected_halfblock[CHACHA_KEY_SIZE] = {
+		0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
+		0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
+		0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
+		0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7 };
+
+	/*
+	 * Expected result when ChaCha20 DRNG state is zero:
+	 *	* constants are set to "expand 32-byte k"
+	 *	* remaining state is 0
+	 * followed by a reseed with two keyblocks
+	 *	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+	 *	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+	 *	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+	 *	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+	 *	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+	 *	0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+	 *	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+	 *	0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f
+	 * and pulling one ChaCha20 DRNG block.
+	 */
+	static u8 const expected_oneblock[CHACHA_KEY_SIZE * 2] = {
+		0xf5, 0xb4, 0xb6, 0x5a, 0xec, 0xcd, 0x5a, 0x65,
+		0x87, 0x56, 0xe3, 0x86, 0x51, 0x54, 0xfc, 0x90,
+		0x56, 0xff, 0x5e, 0xae, 0x58, 0xf2, 0x01, 0x88,
+		0xb1, 0x7e, 0xb8, 0x2e, 0x17, 0x9a, 0x27, 0xe6,
+		0x86, 0xb3, 0xed, 0x33, 0xf7, 0xb9, 0x06, 0x05,
+		0x8a, 0x2d, 0x1a, 0x93, 0xc9, 0x0b, 0x80, 0x04,
+		0x03, 0xaa, 0x60, 0xaf, 0xd5, 0x36, 0x40, 0x11,
+		0x67, 0x89, 0xb1, 0x66, 0xd5, 0x88, 0x62, 0x6d };
+
+	/*
+	 * Expected result when ChaCha20 DRNG state is zero:
+	 *	* constants are set to "expand 32-byte k"
+	 *	* remaining state is 0
+	 * followed by a reseed with one key block plus one byte
+	 *	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+	 *	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+	 *	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+	 *	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+	 *	0x20
+	 * and pulling less than one ChaCha20 DRNG block.
+	 */
+	static u8 const expected_block_nonalinged[CHACHA_KEY_SIZE + 1] = {
+		0x3d, 0x13, 0x47, 0x1e, 0x7f, 0x7c, 0x99, 0x33,
+		0xfc, 0x44, 0xa4, 0xdd, 0xf9, 0x3d, 0xe1, 0x9a,
+		0xd4, 0xe8, 0x7a, 0x7d, 0x42, 0xac, 0xd1, 0xcd,
+		0x10, 0x69, 0xe7, 0xbf, 0xd4, 0xfd, 0x69, 0x4b,
+		0xa7 };
+
+	memset(&chacha20, 0, sizeof(chacha20));
+	lrng_cc20_init_rfc7539(&chacha20);
+
+	/* Generate with zero state */
+	ret = crypto_cb->lrng_drng_generate_helper(&chacha20, outbuf,
+						   sizeof(expected_halfblock));
+	if (ret != sizeof(expected_halfblock))
+		goto err;
+	if (memcmp(outbuf, expected_halfblock, sizeof(expected_halfblock)))
+		goto err;
+
+	/* Clear state of DRNG */
+	memset(&chacha20.key.u[0], 0, 48);
+
+	/* Reseed with 2 key blocks */
+	ret = crypto_cb->lrng_drng_seed_helper(&chacha20, seed,
+					       sizeof(expected_oneblock));
+	if (ret < 0)
+		goto err;
+	ret = crypto_cb->lrng_drng_generate_helper(&chacha20, outbuf,
+						   sizeof(expected_oneblock));
+	if (ret != sizeof(expected_oneblock))
+		goto err;
+	if (memcmp(outbuf, expected_oneblock, sizeof(expected_oneblock)))
+		goto err;
+
+	/* Clear state of DRNG */
+	memset(&chacha20.key.u[0], 0, 48);
+
+	/* Reseed with 1 key block and one byte */
+	ret = crypto_cb->lrng_drng_seed_helper(&chacha20, seed,
+					sizeof(expected_block_nonalinged));
+	if (ret < 0)
+		goto err;
+	ret = crypto_cb->lrng_drng_generate_helper(&chacha20, outbuf,
+					sizeof(expected_block_nonalinged));
+	if (ret != sizeof(expected_block_nonalinged))
+		goto err;
+	if (memcmp(outbuf, expected_block_nonalinged,
+		   sizeof(expected_block_nonalinged)))
+		goto err;
+
+	return LRNG_SELFTEST_PASSED;
+
+err:
+	pr_err("LRNG ChaCha20 DRNG self-test FAILED\n");
+	return LRNG_SEFLTEST_ERROR_CHACHA20;
+}
+
+static int lrng_selftest(void)
+{
+	unsigned int ret = lrng_time_process_selftest();
+
+	ret |= lrng_pool_lfsr_selftest();
+	ret |= lrng_chacha20_drng_selftest();
+	ret |= lrng_hash_df_selftest();
+
+	if (ret) {
+		if (IS_ENABLED(CONFIG_LRNG_SELFTEST_PANIC))
+			panic("LRNG self-tests failed: %u\n", ret);
+	} else {
+		pr_info("LRNG self-tests passed\n");
+	}
+
+	lrng_selftest_status = ret;
+
+	if (lrng_selftest_status)
+		return -EFAULT;
+	return 0;
+}
+
+#ifdef CONFIG_SYSFS
+/* Re-perform self-test when any value is written to the sysfs file. */
+static int lrng_selftest_sysfs_set(const char *val,
+				   const struct kernel_param *kp)
+{
+	return lrng_selftest();
+}
+
+static const struct kernel_param_ops lrng_selftest_sysfs = {
+	.set = lrng_selftest_sysfs_set,
+	.get = param_get_uint,
+};
+module_param_cb(selftest_status, &lrng_selftest_sysfs, &lrng_selftest_status,
+		0644);
+#endif	/* CONFIG_SYSFS */
+
+static int __init lrng_selftest_init(void)
+{
+	return lrng_selftest();
+}
+
+module_init(lrng_selftest_init);
-- 
2.24.1





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* Re: [PATCH v28 01/12] Linux Random Number Generator
  2020-01-15 10:31         ` [PATCH v28 01/12] Linux Random Number Generator Stephan Müller
@ 2020-01-16  0:11           ` Randy Dunlap
  2020-01-16  7:22             ` Stephan Mueller
  0 siblings, 1 reply; 162+ messages in thread
From: Randy Dunlap @ 2020-01-16  0:11 UTC (permalink / raw)
  To: Stephan Müller, Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Julia Lawall, Dan Carpenter

Hi,

On 1/15/20 2:31 AM, Stephan Müller wrote:

> CC: "Eric W. Biederman" <ebiederm@xmission.com>
> CC: "Alexander E. Patrakov" <patrakov@gmail.com>
> CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
> CC: "Theodore Y. Ts'o" <tytso@mit.edu>
> CC: Willy Tarreau <w@1wt.eu>
> CC: Matthew Garrett <mjg59@srcf.ucam.org>
> CC: Vito Caputo <vcaputo@pengaru.com>
> CC: Andreas Dilger <adilger.kernel@dilger.ca>
> CC: Jan Kara <jack@suse.cz>
> CC: Ray Strode <rstrode@redhat.com>
> CC: William Jon McCann <mccann@jhu.edu>
> CC: zhangjs <zachary@baishancloud.com>
> CC: Andy Lutomirski <luto@kernel.org>
> CC: Florian Weimer <fweimer@redhat.com>
> CC: Lennart Poettering <mzxreary@0pointer.de>
> CC: Nicolai Stange <nstange@suse.de>
> Mathematical aspects Reviewed-by: "Peter, Matthias" <matthias.peter@bsi.bund.de>
> Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
> Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
> Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
> Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
> Tested-by: Neil Horman <nhorman@redhat.com>
> Signed-off-by: Stephan Mueller <smueller@chronox.de>
> ---
>  MAINTAINERS                         |   7 +
>  drivers/char/Kconfig                |   2 +
>  drivers/char/Makefile               |   9 +-
>  drivers/char/lrng/Kconfig           |  67 +++
>  drivers/char/lrng/Makefile          |   9 +
>  drivers/char/lrng/lrng_archrandom.c |  94 ++++
>  drivers/char/lrng/lrng_aux.c        | 148 +++++++
>  drivers/char/lrng/lrng_chacha20.c   | 265 ++++++++++++
>  drivers/char/lrng/lrng_chacha20.h   |  25 ++
>  drivers/char/lrng/lrng_drng.c       | 400 +++++++++++++++++
>  drivers/char/lrng/lrng_interfaces.c | 638 ++++++++++++++++++++++++++++
>  drivers/char/lrng/lrng_internal.h   | 296 +++++++++++++
>  drivers/char/lrng/lrng_lfsr.h       | 152 +++++++
>  drivers/char/lrng/lrng_pool.c       | 588 +++++++++++++++++++++++++
>  drivers/char/lrng/lrng_sw_noise.c   | 102 +++++
>  drivers/char/lrng/lrng_sw_noise.h   |  57 +++
>  include/linux/lrng.h                |  63 +++
>  17 files changed, 2921 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/char/lrng/Kconfig
>  create mode 100644 drivers/char/lrng/Makefile
>  create mode 100644 drivers/char/lrng/lrng_archrandom.c
>  create mode 100644 drivers/char/lrng/lrng_aux.c
>  create mode 100644 drivers/char/lrng/lrng_chacha20.c
>  create mode 100644 drivers/char/lrng/lrng_chacha20.h
>  create mode 100644 drivers/char/lrng/lrng_drng.c
>  create mode 100644 drivers/char/lrng/lrng_interfaces.c
>  create mode 100644 drivers/char/lrng/lrng_internal.h
>  create mode 100644 drivers/char/lrng/lrng_lfsr.h
>  create mode 100644 drivers/char/lrng/lrng_pool.c
>  create mode 100644 drivers/char/lrng/lrng_sw_noise.c
>  create mode 100644 drivers/char/lrng/lrng_sw_noise.h
>  create mode 100644 include/linux/lrng.h
> 

> diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
> new file mode 100644
> index 000000000000..56f13efd3592
> --- /dev/null
> +++ b/drivers/char/lrng/Kconfig
> @@ -0,0 +1,67 @@
> +# SPDX-License-Identifier: GPL-2.0
> +#
> +# Linux Random Number Generator configuration
> +#
> +
> +menuconfig LRNG
> +	bool "Linux Random Number Generator"

This should probably depend on CRYPTO and/or some other CRYPTO_xxx symbols.
Or (worst case) select them.  :(

This message (when CONFIG_CRYPTO is disabled and no crypto facilities are enabled)
should be avoidable when the correct Kconfig entries are used:

../drivers/char/lrng/lrng_drbg.c:38:2: error: #error "Unknown DRBG in use"
 #error "Unknown DRBG in use"


> +	help
> +	  The Linux Random Number Generator (LRNG) is the replacement
> +	  of the existing /dev/random provided with drivers/char/random.c.
> +	  It generates entropy from different noise sources and
> +	  delivers significant entropy during boot.
> +
> +if LRNG
> +
> +choice
> +	prompt "LRNG Entropy Pool Size"
> +	default LRNG_POOL_SIZE_4096
> +	help
> +	  Select the size of the LRNG entropy pool. The size of the
> +	  entropy pool is relevant for the amount of entropy that
> +	  the LRNG can maintain as a maximum. The larger the size
> +	  of the entropy pool is the more entropy can be maintained
> +	  but the less often older entropic values are overwritten
> +	  with new entropy.
> +
> +	config LRNG_POOL_SIZE_512
> +		bool "512 bits"
> +
> +	config LRNG_POOL_SIZE_1024
> +		bool "1024 bits"
> +
> +	config LRNG_POOL_SIZE_2048
> +		bool "2048 bits"
> +
> +	config LRNG_POOL_SIZE_4096
> +		bool "4096 bits (default)"
> +
> +	config LRNG_POOL_SIZE_8192
> +		bool "8192 bits"
> +
> +	config LRNG_POOL_SIZE_16384
> +		bool "16384 bits"
> +
> +	config LRNG_POOL_SIZE_32768
> +		bool "32768 bits"
> +
> +	config LRNG_POOL_SIZE_65536
> +		bool "65536 bits"
> +
> +	config LRNG_POOL_SIZE_131072
> +		bool "131072 bits"
> +endchoice
> +
> +config LRNG_POOL_SIZE
> +	int
> +	default 0 if LRNG_POOL_SIZE_512
> +	default 1 if LRNG_POOL_SIZE_1024
> +	default 2 if LRNG_POOL_SIZE_2048
> +	default 3 if LRNG_POOL_SIZE_4096
> +	default 4 if LRNG_POOL_SIZE_8192
> +	default 5 if LRNG_POOL_SIZE_16384
> +	default 6 if LRNG_POOL_SIZE_32768
> +	default 7 if LRNG_POOL_SIZE_65536
> +	default 8 if LRNG_POOL_SIZE_131072
> +
> +endif # LRNG

> diff --git a/drivers/char/lrng/lrng_archrandom.c b/drivers/char/lrng/lrng_archrandom.c
> new file mode 100644
> index 000000000000..eeba708d025f
> --- /dev/null
> +++ b/drivers/char/lrng/lrng_archrandom.c
> @@ -0,0 +1,94 @@
> +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
> +/*
> + * LRNG Fast Noise Source: CPU-based noise source
> + *
> + * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
> + */
> +
> +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> +
> +#include <linux/random.h>
> +
> +#include "lrng_internal.h"
> +
> +/*
> + * Estimated entropy of data is a 32th of LRNG_DRNG_SECURITY_STRENGTH_BITS.
> + * As we have no ability to review the implementation of those noise sources,
> + * it is prudent to have a conservative estimate here.
> + */
> +#define LRNG_ARCHRANDOM_DEFAULT_STRENGTH (LRNG_DRNG_SECURITY_STRENGTH_BITS>>5)
> +#define LRNG_ARCHRANDOM_TRUST_CPU_STRENGTH LRNG_DRNG_SECURITY_STRENGTH_BITS
> +#ifdef CONFIG_RANDOM_TRUST_CPU
> +static u32 archrandom = LRNG_ARCHRANDOM_TRUST_CPU_STRENGTH;
> +#else
> +static u32 archrandom = LRNG_ARCHRANDOM_DEFAULT_STRENGTH;
> +#endif
> +module_param(archrandom, uint, 0644);
> +MODULE_PARM_DESC(archrandom, "Entropy in bits of 256 data bits from CPU noise "
> +			     "source (e.g. RDRAND)");

Please put the string on one line like several other MODULE_PARM_DESC() are done:

+MODULE_PARM_DESC(archrandom,
+		"Entropy in bits of 256 data bits from CPU noise source (e.g. RDRAND)");


With CONFIG_CRYPTO disabled, these warnings happen:

WARNING: unmet direct dependencies detected for CRYPTO_DRBG_MENU
  Depends on [n]: CRYPTO [=n]
  Selected by [m]:
  - LRNG_DRBG [=m] && LRNG [=y] && LRNG_DRNG_SWITCH [=y]

WARNING: unmet direct dependencies detected for CRYPTO_RNG
  Depends on [n]: CRYPTO [=n]
  Selected by [m]:
  - LRNG_KCAPI [=m] && LRNG [=y] && LRNG_DRNG_SWITCH [=y]

../drivers/char/lrng/lrng_drbg.c: In function ‘lrng_hash_name’:
../drivers/char/lrng/lrng_drbg.c:225:1: warning: control reaches end of non-void function [-Wreturn-type]
 }
 ^
../drivers/char/lrng/lrng_drbg.c: In function ‘lrng_drbg_name’:
../drivers/char/lrng/lrng_drbg.c:220:1: warning: control reaches end of non-void function [-Wreturn-type]
 }
 ^

and build errors happen also, which can be prevented with Kconfig fixes.

-- 
~Randy
Reported-by: Randy Dunlap <rdunlap@infradead.org>

^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v28 06/12] LRNG - add SP800-90A DRBG extension
  2020-01-15 10:33         ` [PATCH v28 06/12] LRNG - add SP800-90A DRBG extension Stephan Müller
@ 2020-01-16  0:14           ` Randy Dunlap
  2020-01-16  6:55             ` Stephan Mueller
  0 siblings, 1 reply; 162+ messages in thread
From: Randy Dunlap @ 2020-01-16  0:14 UTC (permalink / raw)
  To: Stephan Müller, Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Julia Lawall, Dan Carpenter

On 1/15/20 2:33 AM, Stephan Müller wrote:

> 
> CC: "Eric W. Biederman" <ebiederm@xmission.com>
> CC: "Alexander E. Patrakov" <patrakov@gmail.com>
> CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
> CC: "Theodore Y. Ts'o" <tytso@mit.edu>
> CC: Willy Tarreau <w@1wt.eu>
> CC: Matthew Garrett <mjg59@srcf.ucam.org>
> CC: Vito Caputo <vcaputo@pengaru.com>
> CC: Andreas Dilger <adilger.kernel@dilger.ca>
> CC: Jan Kara <jack@suse.cz>
> CC: Ray Strode <rstrode@redhat.com>
> CC: William Jon McCann <mccann@jhu.edu>
> CC: zhangjs <zachary@baishancloud.com>
> CC: Andy Lutomirski <luto@kernel.org>
> CC: Florian Weimer <fweimer@redhat.com>
> CC: Lennart Poettering <mzxreary@0pointer.de>
> CC: Nicolai Stange <nstange@suse.de>
> Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
> Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
> Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
> Tested-by: Neil Horman <nhorman@redhat.com>
> Signed-off-by: Stephan Mueller <smueller@chronox.de>
> ---
>  drivers/char/lrng/Kconfig     |  11 ++
>  drivers/char/lrng/Makefile    |   1 +
>  drivers/char/lrng/lrng_drbg.c | 260 ++++++++++++++++++++++++++++++++++
>  3 files changed, 272 insertions(+)
>  create mode 100644 drivers/char/lrng/lrng_drbg.c
> 
> diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
> index cb701bb0b8b6..15fb623d9d1f 100644
> --- a/drivers/char/lrng/Kconfig
> +++ b/drivers/char/lrng/Kconfig
> @@ -71,4 +71,15 @@ menuconfig LRNG_DRNG_SWITCH
>  	  accessible via the external interfaces. With this configuration
>  	  option other DRNGs can be selected and loaded at runtime.
>  
> +if LRNG_DRNG_SWITCH
> +config LRNG_DRBG
> +	tristate "SP800-90A support for the LRNG"
> +	select CRYPTO_DRBG_MENU
> +	select CRYPTO_CMAC if CRYPTO_DRBG_CTR

Don't select these if CRYPTO is not already set/enabled.
It causes Kconfig warnings and possible build errors.

> +	help
> +	  Enable the SP800-90A DRBG support for the LRNG. Once the
> +	  module is loaded, output from /dev/random, /dev/urandom,
> +	  getrandom(2), or get_random_bytes is provided by a DRBG.
> +endif # LRNG_DRNG_SWITCH
> +
>  endif # LRNG

> diff --git a/drivers/char/lrng/lrng_drbg.c b/drivers/char/lrng/lrng_drbg.c
> new file mode 100644
> index 000000000000..8bf2badb1fe0
> --- /dev/null
> +++ b/drivers/char/lrng/lrng_drbg.c
> @@ -0,0 +1,260 @@
> +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
> +/*
> + * Backend for the LRNG providing the cryptographic primitives using the
> + * kernel crypto API and its DRBG.
> + *
> + * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
> + */
> +
> +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> +
> +#include <crypto/drbg.h>
> +#include <linux/init.h>
> +#include <linux/module.h>
> +#include <linux/lrng.h>
> +
> +/*
> + * Define a DRBG plus a hash / MAC used to extract data from the entropy pool.
> + * For LRNG_HASH_NAME you can use a hash or a MAC (HMAC or CMAC) of your choice
> + * (Note, you should use the suggested selections below -- using SHA-1 or MD5
> + * is not wise). The idea is that the used cipher primitive can be selected to
> + * be the same as used for the DRBG. I.e. the LRNG only uses one cipher
> + * primitive using the same cipher implementation with the options offered in
> + * the following. This means, if the CTR DRBG is selected and AES-NI is present,
> + * both the CTR DRBG and the selected cmac(aes) use AES-NI.
> + *
> + * The security strengths of the DRBGs are all 256 bits according to
> + * SP800-57 section 5.6.1.
> + *
> + * This definition is allowed to be changed.
> + */
> +#ifdef CONFIG_CRYPTO_DRBG_CTR
> +static unsigned int lrng_drbg_type = 0;
> +#elif defined CONFIG_CRYPTO_DRBG_HMAC
> +static unsigned int lrng_drbg_type = 1;
> +#elif defined CONFIG_CRYPTO_DRBG_HASH
> +static unsigned int lrng_drbg_type = 2;
> +#else
> +#error "Unknown DRBG in use"
> +#endif
> +
> +/* The parameter must be r/o in sysfs as otherwise races appear. */
> +module_param(lrng_drbg_type, uint, 0444);
> +MODULE_PARM_DESC(lrng_drbg_type, "DRBG type used for LRNG (0->CTR_DRBG, "
> +				 "1->HMAC_DRBG, 2->Hash_DRBG)");

One line for the string, please, not split.

-- 
~Randy
Reported-by: Randy Dunlap <rdunlap@infradead.org>

^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v28 07/12] LRNG - add kernel crypto API PRNG extension
  2020-01-15 10:34         ` [PATCH v28 07/12] LRNG - add kernel crypto API PRNG extension Stephan Müller
@ 2020-01-16  0:15           ` Randy Dunlap
  2020-01-16  6:54             ` Stephan Mueller
  0 siblings, 1 reply; 162+ messages in thread
From: Randy Dunlap @ 2020-01-16  0:15 UTC (permalink / raw)
  To: Stephan Müller, Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Julia Lawall, Dan Carpenter

On 1/15/20 2:34 AM, Stephan Müller wrote:
> 
> CC: "Eric W. Biederman" <ebiederm@xmission.com>
> CC: "Alexander E. Patrakov" <patrakov@gmail.com>
> CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
> CC: "Theodore Y. Ts'o" <tytso@mit.edu>
> CC: Willy Tarreau <w@1wt.eu>
> CC: Matthew Garrett <mjg59@srcf.ucam.org>
> CC: Vito Caputo <vcaputo@pengaru.com>
> CC: Andreas Dilger <adilger.kernel@dilger.ca>
> CC: Jan Kara <jack@suse.cz>
> CC: Ray Strode <rstrode@redhat.com>
> CC: William Jon McCann <mccann@jhu.edu>
> CC: zhangjs <zachary@baishancloud.com>
> CC: Andy Lutomirski <luto@kernel.org>
> CC: Florian Weimer <fweimer@redhat.com>
> CC: Lennart Poettering <mzxreary@0pointer.de>
> CC: Nicolai Stange <nstange@suse.de>
> Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
> Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
> Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
> Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
> Tested-by: Neil Horman <nhorman@redhat.com>
> Signed-off-by: Stephan Mueller <smueller@chronox.de>
> ---
>  drivers/char/lrng/Kconfig      |  10 +
>  drivers/char/lrng/Makefile     |   1 +
>  drivers/char/lrng/lrng_kcapi.c | 327 +++++++++++++++++++++++++++++++++
>  3 files changed, 338 insertions(+)
>  create mode 100644 drivers/char/lrng/lrng_kcapi.c
> 
> diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
> index 15fb623d9d1f..0d070a3897dd 100644
> --- a/drivers/char/lrng/Kconfig
> +++ b/drivers/char/lrng/Kconfig
> @@ -80,6 +80,16 @@ config LRNG_DRBG
>  	  Enable the SP800-90A DRBG support for the LRNG. Once the
>  	  module is loaded, output from /dev/random, /dev/urandom,
>  	  getrandom(2), or get_random_bytes is provided by a DRBG.
> +
> +config LRNG_KCAPI
> +	tristate "Kernel Crypto API support for the LRNG"
> +	select CRYPTO_RNG

Don't select CRYPTO_RNG unless you know that CRYPTO is set/enabled.

> +	help
> +	  Enable the support for generic pseudo-random number
> +	  generators offered by the kernel crypto API with the
> +	  LRNG. Once the module is loaded, output from /dev/random,
> +	  /dev/urandom, getrandom(2), or get_random_bytes is
> +	  provided by the selected kernel crypto API RNG.
>  endif # LRNG_DRNG_SWITCH
>  
>  endif # LRNG


-- 
~Randy
Reported-by: Randy Dunlap <rdunlap@infradead.org>

^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v28 09/12] LRNG - add Jitter RNG fast noise source
  2020-01-15 10:34         ` [PATCH v28 09/12] LRNG - add Jitter RNG fast noise source Stephan Müller
@ 2020-01-16  0:17           ` Randy Dunlap
  2020-01-16  6:51             ` Stephan Mueller
  0 siblings, 1 reply; 162+ messages in thread
From: Randy Dunlap @ 2020-01-16  0:17 UTC (permalink / raw)
  To: Stephan Müller, Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Julia Lawall, Dan Carpenter

On 1/15/20 2:34 AM, Stephan Müller wrote:

> 
> CC: "Eric W. Biederman" <ebiederm@xmission.com>
> CC: "Alexander E. Patrakov" <patrakov@gmail.com>
> CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
> CC: "Theodore Y. Ts'o" <tytso@mit.edu>
> CC: Willy Tarreau <w@1wt.eu>
> CC: Matthew Garrett <mjg59@srcf.ucam.org>
> CC: Vito Caputo <vcaputo@pengaru.com>
> CC: Andreas Dilger <adilger.kernel@dilger.ca>
> CC: Jan Kara <jack@suse.cz>
> CC: Ray Strode <rstrode@redhat.com>
> CC: William Jon McCann <mccann@jhu.edu>
> CC: zhangjs <zachary@baishancloud.com>
> CC: Andy Lutomirski <luto@kernel.org>
> CC: Florian Weimer <fweimer@redhat.com>
> CC: Lennart Poettering <mzxreary@0pointer.de>
> CC: Nicolai Stange <nstange@suse.de>
> Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
> Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
> Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
> Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
> Tested-by: Neil Horman <nhorman@redhat.com>
> Signed-off-by: Stephan Mueller <smueller@chronox.de>
> ---
>  drivers/char/lrng/Kconfig     | 11 +++++
>  drivers/char/lrng/Makefile    |  1 +
>  drivers/char/lrng/lrng_jent.c | 89 +++++++++++++++++++++++++++++++++++
>  3 files changed, 101 insertions(+)
>  create mode 100644 drivers/char/lrng/lrng_jent.c
> 
> diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
> index 0d070a3897dd..10b7cbdb8c8e 100644
> --- a/drivers/char/lrng/Kconfig
> +++ b/drivers/char/lrng/Kconfig
> @@ -92,4 +92,15 @@ config LRNG_KCAPI
>  	  provided by the selected kernel crypto API RNG.
>  endif # LRNG_DRNG_SWITCH
>  
> +config LRNG_JENT
> +	bool "Enable Jitter RNG as LRNG Seed Source"
> +	select CRYPTO_JITTERENTROPY

Don't select unless CRYPTO is already set/enabled.

> +	help
> +	  The Linux RNG may use the Jitter RNG as noise source. Enabling
> +	  this option enables the use of the Jitter RNG. Its default
> +	  entropy level is 16 bits of entropy per 256 data bits delivered
> +	  by the Jitter RNG. This entropy level can be changed at boot
> +	  time or at runtime with the lrng_base.jitterrng configuration
> +	  variable.
> +
>  endif # LRNG

> diff --git a/drivers/char/lrng/lrng_jent.c b/drivers/char/lrng/lrng_jent.c
> new file mode 100644
> index 000000000000..ff0bbe2680c4
> --- /dev/null
> +++ b/drivers/char/lrng/lrng_jent.c
> @@ -0,0 +1,89 @@
> +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
> +/*
> + * LRNG Fast Noise Source: Jitter RNG
> + *
> + * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
> + */
> +
> +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> +
> +#include <linux/types.h>
> +#include <crypto/internal/jitterentropy.h>
> +
> +#include "lrng_internal.h"
> +
> +/*
> + * Estimated entropy of data is a 16th of LRNG_DRNG_SECURITY_STRENGTH_BITS.
> + * Albeit a full entropy assessment is provided for the noise source indicating
> + * that it provides high entropy rates and considering that it deactivates
> + * when it detects insufficient hardware, the chosen under estimation of
> + * entropy is considered to be acceptable to all reviewers.
> + */
> +static u32 jitterrng = LRNG_DRNG_SECURITY_STRENGTH_BITS>>4;
> +module_param(jitterrng, uint, 0644);
> +MODULE_PARM_DESC(jitterrng, "Entropy in bits of 256 data bits from Jitter "
> +			    "RNG noise source");

One line for the string, please, not split to 2 lines.

-- 
~Randy
Reported-by: Randy Dunlap <rdunlap@infradead.org>

^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v28 11/12] LRNG - add interface for gathering of raw entropy
  2020-01-15 10:35         ` [PATCH v28 11/12] LRNG - add interface for gathering of raw entropy Stephan Müller
@ 2020-01-16  0:18           ` Randy Dunlap
  2020-01-16  6:43             ` Stephan Mueller
  0 siblings, 1 reply; 162+ messages in thread
From: Randy Dunlap @ 2020-01-16  0:18 UTC (permalink / raw)
  To: Stephan Müller, Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Julia Lawall, Dan Carpenter

On 1/15/20 2:35 AM, Stephan Müller wrote:

> 
> CC: "Eric W. Biederman" <ebiederm@xmission.com>
> CC: "Alexander E. Patrakov" <patrakov@gmail.com>
> CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
> CC: "Theodore Y. Ts'o" <tytso@mit.edu>
> CC: Willy Tarreau <w@1wt.eu>
> CC: Matthew Garrett <mjg59@srcf.ucam.org>
> CC: Vito Caputo <vcaputo@pengaru.com>
> CC: Andreas Dilger <adilger.kernel@dilger.ca>
> CC: Jan Kara <jack@suse.cz>
> CC: Ray Strode <rstrode@redhat.com>
> CC: William Jon McCann <mccann@jhu.edu>
> CC: zhangjs <zachary@baishancloud.com>
> CC: Andy Lutomirski <luto@kernel.org>
> CC: Florian Weimer <fweimer@redhat.com>
> CC: Lennart Poettering <mzxreary@0pointer.de>
> CC: Nicolai Stange <nstange@suse.de>
> Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
> Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
> Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
> Tested-by: Neil Horman <nhorman@redhat.com>
> Signed-off-by: Stephan Mueller <smueller@chronox.de>
> ---
>  drivers/char/lrng/Kconfig        |  16 ++
>  drivers/char/lrng/Makefile       |   1 +
>  drivers/char/lrng/lrng_testing.c | 271 +++++++++++++++++++++++++++++++
>  3 files changed, 288 insertions(+)
>  create mode 100644 drivers/char/lrng/lrng_testing.c
> 

> diff --git a/drivers/char/lrng/lrng_testing.c b/drivers/char/lrng/lrng_testing.c
> new file mode 100644
> index 000000000000..0e287eccd622
> --- /dev/null
> +++ b/drivers/char/lrng/lrng_testing.c
> @@ -0,0 +1,271 @@
> +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
> +/*
> + * Linux Random Number Generator (LRNG) Raw entropy collection tool
> + *
> + * Copyright (C) 2019 - 2020, Stephan Mueller <smueller@chronox.de>
> + */
> +
> +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> +
> +#include <linux/atomic.h>
> +#include <linux/bug.h>
> +#include <linux/debugfs.h>
> +#include <linux/module.h>
> +#include <linux/sched.h>
> +#include <linux/sched/signal.h>
> +#include <linux/slab.h>
> +#include <linux/string.h>
> +#include <linux/types.h>
> +#include <linux/uaccess.h>
> +#include <linux/workqueue.h>
> +#include <asm/errno.h>
> +
> +#include "lrng_internal.h"
> +
> +#define LRNG_TESTING_RINGBUFFER_SIZE	1024
> +#define LRNG_TESTING_RINGBUFFER_MASK	(LRNG_TESTING_RINGBUFFER_SIZE - 1)
> +
> +static u32 lrng_testing_rb[LRNG_TESTING_RINGBUFFER_SIZE];
> +static u32 lrng_rb_reader = 0;
> +static u32 lrng_rb_writer = 0;
> +static atomic_t lrng_testing_enabled = ATOMIC_INIT(0);
> +
> +static DECLARE_WAIT_QUEUE_HEAD(lrng_raw_read_wait);
> +static DEFINE_SPINLOCK(lrng_raw_lock);
> +
> +/*
> + * 0 ==> No boot test, gathering of runtime data allowed
> + * 1 ==> Boot test enabled and ready for collecting data, gathering runtime
> + *	 data is disabled
> + * 2 ==> Boot test completed and disabled, gathering of runtime data is
> + *	 disabled
> + */
> +static u32 boot_test = 0;
> +module_param(boot_test, uint, 0644);
> +MODULE_PARM_DESC(boot_test, "Enable gathering boot time entropy of the first"
> +			    " entropy events");

One line for the string, please.


-- 
~Randy
Reported-by: Randy Dunlap <rdunlap@infradead.org>

^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v27 01/12] Linux Random Number Generator
  2020-01-09  8:30       ` [PATCH v27 01/12] Linux Random Number Generator Stephan Müller
@ 2020-01-16  6:09         ` kbuild test robot
  2020-01-16  6:41           ` Stephan Mueller
  0 siblings, 1 reply; 162+ messages in thread
From: kbuild test robot @ 2020-01-16  6:09 UTC (permalink / raw)
  To: Stephan Müller
  Cc: kbuild-all, Arnd Bergmann, Greg Kroah-Hartman, linux-crypto,
	LKML, linux-api, Eric W. Biederman, Alexander E. Patrakov,
	Ahmed S. Darwish, Theodore Y. Ts'o, Willy Tarreau,
	Matthew Garrett, Vito Caputo, Andreas Dilger, Jan Kara,
	Ray Strode, William Jon McCann, zhangjs, Andy Lutomirski,
	Florian Weimer, Lennart Poettering, Nicolai Stange, Peter,
	Matthias, Marcelo Henrique Cerri, Roman Drahtmueller,
	Neil Horman, Randy Dunlap, Julia Lawall

Hi "Stephan,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on char-misc/char-misc-testing]
[also build test WARNING on cryptodev/master crypto/master v5.5-rc6 next-20200110]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]

url:    https://github.com/0day-ci/linux/commits/Stephan-M-ller/dev-random-a-new-approach-with-full-SP800-90B/20200110-084934
base:   https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git 68faa679b8be1a74e6663c21c3a9d25d32f1c079
reproduce:
        # apt-get install sparse
        # sparse version: v0.6.1-130-g1a803e7a-dirty
        make ARCH=x86_64 allmodconfig
        make C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__'

If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@intel.com>


sparse warnings: (new ones prefixed by >>)

>> drivers/char/lrng/lrng_interfaces.c:455:16: sparse: sparse: incorrect type in return expression (different base types)
>> drivers/char/lrng/lrng_interfaces.c:455:16: sparse:    expected unsigned int
>> drivers/char/lrng/lrng_interfaces.c:455:16: sparse:    got restricted __poll_t [assigned] [usertype] mask
>> drivers/char/lrng/lrng_interfaces.c:586:18: sparse: sparse: incorrect type in initializer (different base types)
>> drivers/char/lrng/lrng_interfaces.c:586:18: sparse:    expected restricted __poll_t ( *poll )( ... )
>> drivers/char/lrng/lrng_interfaces.c:586:18: sparse:    got unsigned int ( * )( ... )
   drivers/char/lrng/lrng_interfaces.c:605:49: sparse: sparse: undefined identifier 'GRND_INSECURE'
   drivers/char/lrng/lrng_interfaces.c:613:15: sparse: sparse: undefined identifier 'GRND_INSECURE'
   drivers/char/lrng/lrng_interfaces.c:613:47: sparse: sparse: undefined identifier 'GRND_INSECURE'
   drivers/char/lrng/lrng_interfaces.c:619:21: sparse: sparse: undefined identifier 'GRND_INSECURE'
--
   drivers/char/lrng/lrng_drng.c:378:6: sparse: sparse: symbol 'lrng_reset' was not declared. Should it be static?
>> drivers/char/lrng/lrng_internal.h:235:39: sparse: sparse: context imbalance in 'lrng_drng_inject' - unexpected unlock
>> drivers/char/lrng/lrng_internal.h:235:39: sparse: sparse: context imbalance in 'lrng_drng_seed' - unexpected unlock
>> drivers/char/lrng/lrng_internal.h:235:39: sparse: sparse: context imbalance in 'lrng_drng_get' - unexpected unlock
>> drivers/char/lrng/lrng_internal.h:235:39: sparse: sparse: context imbalance in 'lrng_drngs_init_cc20' - unexpected unlock
>> drivers/char/lrng/lrng_internal.h:235:39: sparse: sparse: context imbalance in '_lrng_reset' - unexpected unlock

vim +455 drivers/char/lrng/lrng_interfaces.c

   442	
   443	static unsigned int lrng_random_poll(struct file *file, poll_table *wait)
   444	{
   445		__poll_t mask;
   446	
   447		poll_wait(file, &lrng_init_wait, wait);
   448		poll_wait(file, &lrng_write_wait, wait);
   449		mask = 0;
   450		if (lrng_state_operational())
   451			mask |= EPOLLIN | EPOLLRDNORM;
   452		if (lrng_need_entropy() ||
   453		    lrng_state_exseed_allow(lrng_noise_source_user))
   454			mask |= EPOLLOUT | EPOLLWRNORM;
 > 455		return mask;
   456	}
   457	
   458	static ssize_t lrng_drng_write_common(const char __user *buffer, size_t count,
   459					      u32 entropy_bits)
   460	{
   461		ssize_t ret = 0;
   462		u8 buf[64] __aligned(LRNG_KCAPI_ALIGN);
   463		const char __user *p = buffer;
   464		u32 orig_entropy_bits = entropy_bits;
   465	
   466		if (!lrng_get_available())
   467			return -EAGAIN;
   468	
   469		count = min_t(size_t, count, INT_MAX);
   470		while (count > 0) {
   471			size_t bytes = min_t(size_t, count, sizeof(buf));
   472			u32 ent = min_t(u32, bytes<<3, entropy_bits);
   473	
   474			if (copy_from_user(&buf, p, bytes))
   475				return -EFAULT;
   476			/* Inject data into entropy pool */
   477			lrng_pool_lfsr(buf, bytes);
   478			lrng_pool_add_entropy(ent);
   479	
   480			count -= bytes;
   481			p += bytes;
   482			ret += bytes;
   483			entropy_bits -= ent;
   484	
   485			cond_resched();
   486		}
   487	
   488		/* Force reseed of DRNG during next data request. */
   489		if (!orig_entropy_bits)
   490			lrng_drng_force_reseed();
   491	
   492		return ret;
   493	}
   494	
   495	static ssize_t lrng_drng_read(struct file *file, char __user *buf,
   496				      size_t nbytes, loff_t *ppos)
   497	{
   498		if (!lrng_state_min_seeded())
   499			pr_notice_ratelimited("%s - use of insufficiently seeded DRNG "
   500					      "(%zu bytes read)\n", current->comm,
   501					      nbytes);
   502		else if (!lrng_state_operational())
   503			pr_debug_ratelimited("%s - use of not fully seeded DRNG (%zu "
   504					     "bytes read)\n", current->comm, nbytes);
   505	
   506		return lrng_read_common(buf, nbytes);
   507	}
   508	
   509	static ssize_t lrng_drng_write(struct file *file, const char __user *buffer,
   510				       size_t count, loff_t *ppos)
   511	{
   512		return lrng_drng_write_common(buffer, count, 0);
   513	}
   514	
   515	static long lrng_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
   516	{
   517		int size, ent_count_bits;
   518		int __user *p = (int __user *)arg;
   519	
   520		switch (cmd) {
   521		case RNDGETENTCNT:
   522			ent_count_bits = lrng_avail_entropy();
   523			if (put_user(ent_count_bits, p))
   524				return -EFAULT;
   525			return 0;
   526		case RNDADDTOENTCNT:
   527			if (!capable(CAP_SYS_ADMIN))
   528				return -EPERM;
   529			if (get_user(ent_count_bits, p))
   530				return -EFAULT;
   531			ent_count_bits = (int)lrng_avail_entropy() + ent_count_bits;
   532			if (ent_count_bits < 0)
   533				ent_count_bits = 0;
   534			if (ent_count_bits > LRNG_POOL_SIZE_BITS)
   535				ent_count_bits = LRNG_POOL_SIZE_BITS;
   536			lrng_pool_set_entropy(ent_count_bits);
   537			return 0;
   538		case RNDADDENTROPY:
   539			if (!capable(CAP_SYS_ADMIN))
   540				return -EPERM;
   541			if (get_user(ent_count_bits, p++))
   542				return -EFAULT;
   543			if (ent_count_bits < 0)
   544				return -EINVAL;
   545			if (get_user(size, p++))
   546				return -EFAULT;
   547			if (size < 0)
   548				return -EINVAL;
   549			lrng_state_exseed_set(lrng_noise_source_user, false);
   550			/* there cannot be more entropy than data */
   551			ent_count_bits = min(ent_count_bits, size<<3);
   552			return lrng_drng_write_common((const char __user *)p, size,
   553						      ent_count_bits);
   554		case RNDZAPENTCNT:
   555		case RNDCLEARPOOL:
   556			/* Clear the entropy pool counter. */
   557			if (!capable(CAP_SYS_ADMIN))
   558				return -EPERM;
   559			lrng_pool_set_entropy(0);
   560			return 0;
   561		case RNDRESEEDCRNG:
   562			/*
   563			 * We leave the capability check here since it is present
   564			 * in the upstream's RNG implementation. Yet, user space
   565			 * can trigger a reseed as easy as writing into /dev/random
   566			 * or /dev/urandom where no privilege is needed.
   567			 */
   568			if (!capable(CAP_SYS_ADMIN))
   569				return -EPERM;
   570			/* Force a reseed of all DRNGs */
   571			lrng_drng_force_reseed();
   572			return 0;
   573		default:
   574			return -EINVAL;
   575		}
   576	}
   577	
   578	static int lrng_fasync(int fd, struct file *filp, int on)
   579	{
   580		return fasync_helper(fd, filp, on, &fasync);
   581	}
   582	
   583	const struct file_operations random_fops = {
   584		.read  = lrng_drng_read_block,
   585		.write = lrng_drng_write,
 > 586		.poll  = lrng_random_poll,
   587		.unlocked_ioctl = lrng_ioctl,
   588		.compat_ioctl = compat_ptr_ioctl,
   589		.fasync = lrng_fasync,
   590		.llseek = noop_llseek,
   591	};
   592	

---
0-DAY kernel test infrastructure                 Open Source Technology Center
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org Intel Corporation

^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v27 01/12] Linux Random Number Generator
  2020-01-16  6:09         ` kbuild test robot
@ 2020-01-16  6:41           ` Stephan Mueller
  0 siblings, 0 replies; 162+ messages in thread
From: Stephan Mueller @ 2020-01-16  6:41 UTC (permalink / raw)
  To: kbuild test robot
  Cc: kbuild-all, Arnd Bergmann, Greg Kroah-Hartman, linux-crypto,
	LKML, linux-api, Eric W. Biederman, Alexander E. Patrakov,
	Ahmed S. Darwish, Theodore Y. Ts'o, Willy Tarreau,
	Matthew Garrett, Vito Caputo, Andreas Dilger, Jan Kara,
	Ray Strode, William Jon McCann, zhangjs, Andy Lutomirski,
	Florian Weimer, Lennart Poettering, Nicolai Stange, Peter,
	Matthias, Marcelo Henrique Cerri, Roman Drahtmueller,
	Neil Horman, Randy Dunlap, Julia Lawall

Am Donnerstag, 16. Januar 2020, 07:09:51 CET schrieb kbuild test robot:

Hi kbuild,

> Hi "Stephan,
> 
> Thank you for the patch! Perhaps something to improve:
> 
> [auto build test WARNING on char-misc/char-misc-testing]
> [also build test WARNING on cryptodev/master crypto/master v5.5-rc6
> next-20200110] [if your patch is applied to the wrong git tree, please drop
> us a note to help improve the system. BTW, we also suggest to use '--base'
> option to specify the base tree in git format-patch, please see
> https://stackoverflow.com/a/37406982]

This patch requires the presence of patch 
75551dbf112c992bc6c99a972990b3f272247e23 from Ted Tso's kernel tree as 
documented in patch 0/12.

I am not sure how to document it for the kbuild system.
> 
> url:   
> https://github.com/0day-ci/linux/commits/Stephan-M-ller/dev-random-a-new-ap
> proach-with-full-SP800-90B/20200110-084934 base:  
> https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git
> 68faa679b8be1a74e6663c21c3a9d25d32f1c079 reproduce:
>         # apt-get install sparse
>         # sparse version: v0.6.1-130-g1a803e7a-dirty
>         make ARCH=x86_64 allmodconfig
>         make C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__'
> 
> If you fix the issue, kindly add following tag
> Reported-by: kbuild test robot <lkp@intel.com>
> 
> 
> sparse warnings: (new ones prefixed by >>)
> 
> >> drivers/char/lrng/lrng_interfaces.c:455:16: sparse: sparse: incorrect
> >> type in return expression (different base types)
> >> drivers/char/lrng/lrng_interfaces.c:455:16: sparse:    expected unsigned
> >> int drivers/char/lrng/lrng_interfaces.c:455:16: sparse:    got
> >> restricted __poll_t [assigned] [usertype] mask
> >> drivers/char/lrng/lrng_interfaces.c:586:18: sparse: sparse: incorrect
> >> type in initializer (different base types)
> >> drivers/char/lrng/lrng_interfaces.c:586:18: sparse:    expected
> >> restricted __poll_t ( *poll )( ... )
> >> drivers/char/lrng/lrng_interfaces.c:586:18: sparse:    got unsigned int
> >> ( * )( ... )
>    drivers/char/lrng/lrng_interfaces.c:605:49: sparse: sparse: undefined
> identifier 'GRND_INSECURE' drivers/char/lrng/lrng_interfaces.c:613:15:
> sparse: sparse: undefined identifier 'GRND_INSECURE'
> drivers/char/lrng/lrng_interfaces.c:613:47: sparse: sparse: undefined
> identifier 'GRND_INSECURE' drivers/char/lrng/lrng_interfaces.c:619:21:
> sparse: sparse: undefined identifier 'GRND_INSECURE' --
>    drivers/char/lrng/lrng_drng.c:378:6: sparse: sparse: symbol 'lrng_reset'
> was not declared. Should it be static?
> >> drivers/char/lrng/lrng_internal.h:235:39: sparse: sparse: context
> >> imbalance in 'lrng_drng_inject' - unexpected unlock
> >> drivers/char/lrng/lrng_internal.h:235:39: sparse: sparse: context
> >> imbalance in 'lrng_drng_seed' - unexpected unlock
> >> drivers/char/lrng/lrng_internal.h:235:39: sparse: sparse: context
> >> imbalance in 'lrng_drng_get' - unexpected unlock
> >> drivers/char/lrng/lrng_internal.h:235:39: sparse: sparse: context
> >> imbalance in 'lrng_drngs_init_cc20' - unexpected unlock
> >> drivers/char/lrng/lrng_internal.h:235:39: sparse: sparse: context
> >> imbalance in '_lrng_reset' - unexpected unlock
> vim +455 drivers/char/lrng/lrng_interfaces.c
> 
>    442
>    443	static unsigned int lrng_random_poll(struct file *file, poll_table
> *wait) 444	{
>    445		__poll_t mask;
>    446
>    447		poll_wait(file, &lrng_init_wait, wait);
>    448		poll_wait(file, &lrng_write_wait, wait);
>    449		mask = 0;
>    450		if (lrng_state_operational())
>    451			mask |= EPOLLIN | EPOLLRDNORM;
>    452		if (lrng_need_entropy() ||
>    453		    lrng_state_exseed_allow(lrng_noise_source_user))
>    454			mask |= EPOLLOUT | EPOLLWRNORM;
> 
>  > 455		return mask;
> 
>    456	}
>    457
>    458	static ssize_t lrng_drng_write_common(const char __user *buffer,
> size_t count, 459					      u32 
entropy_bits)
>    460	{
>    461		ssize_t ret = 0;
>    462		u8 buf[64] __aligned(LRNG_KCAPI_ALIGN);
>    463		const char __user *p = buffer;
>    464		u32 orig_entropy_bits = entropy_bits;
>    465
>    466		if (!lrng_get_available())
>    467			return -EAGAIN;
>    468
>    469		count = min_t(size_t, count, INT_MAX);
>    470		while (count > 0) {
>    471			size_t bytes = min_t(size_t, count, sizeof(buf));
>    472			u32 ent = min_t(u32, bytes<<3, entropy_bits);
>    473
>    474			if (copy_from_user(&buf, p, bytes))
>    475				return -EFAULT;
>    476			/* Inject data into entropy pool */
>    477			lrng_pool_lfsr(buf, bytes);
>    478			lrng_pool_add_entropy(ent);
>    479
>    480			count -= bytes;
>    481			p += bytes;
>    482			ret += bytes;
>    483			entropy_bits -= ent;
>    484
>    485			cond_resched();
>    486		}
>    487
>    488		/* Force reseed of DRNG during next data request. */
>    489		if (!orig_entropy_bits)
>    490			lrng_drng_force_reseed();
>    491
>    492		return ret;
>    493	}
>    494
>    495	static ssize_t lrng_drng_read(struct file *file, char __user *buf,
>    496				      size_t nbytes, loff_t *ppos)
>    497	{
>    498		if (!lrng_state_min_seeded())
>    499			pr_notice_ratelimited("%s - use of insufficiently 
seeded DRNG "
>    500					      "(%zu bytes read)\n", current-
>comm,
>    501					      nbytes);
>    502		else if (!lrng_state_operational())
>    503			pr_debug_ratelimited("%s - use of not fully seeded 
DRNG (%zu "
>    504					     "bytes read)\n", current->comm, 
nbytes);
>    505
>    506		return lrng_read_common(buf, nbytes);
>    507	}
>    508
>    509	static ssize_t lrng_drng_write(struct file *file, const char __user
> *buffer, 510				       size_t count, loff_t *ppos)
>    511	{
>    512		return lrng_drng_write_common(buffer, count, 0);
>    513	}
>    514
>    515	static long lrng_ioctl(struct file *f, unsigned int cmd, unsigned
> long arg) 516	{
>    517		int size, ent_count_bits;
>    518		int __user *p = (int __user *)arg;
>    519
>    520		switch (cmd) {
>    521		case RNDGETENTCNT:
>    522			ent_count_bits = lrng_avail_entropy();
>    523			if (put_user(ent_count_bits, p))
>    524				return -EFAULT;
>    525			return 0;
>    526		case RNDADDTOENTCNT:
>    527			if (!capable(CAP_SYS_ADMIN))
>    528				return -EPERM;
>    529			if (get_user(ent_count_bits, p))
>    530				return -EFAULT;
>    531			ent_count_bits = (int)lrng_avail_entropy() + 
ent_count_bits;
>    532			if (ent_count_bits < 0)
>    533				ent_count_bits = 0;
>    534			if (ent_count_bits > LRNG_POOL_SIZE_BITS)
>    535				ent_count_bits = LRNG_POOL_SIZE_BITS;
>    536			lrng_pool_set_entropy(ent_count_bits);
>    537			return 0;
>    538		case RNDADDENTROPY:
>    539			if (!capable(CAP_SYS_ADMIN))
>    540				return -EPERM;
>    541			if (get_user(ent_count_bits, p++))
>    542				return -EFAULT;
>    543			if (ent_count_bits < 0)
>    544				return -EINVAL;
>    545			if (get_user(size, p++))
>    546				return -EFAULT;
>    547			if (size < 0)
>    548				return -EINVAL;
>    549			lrng_state_exseed_set(lrng_noise_source_user, false);
>    550			/* there cannot be more entropy than data */
>    551			ent_count_bits = min(ent_count_bits, size<<3);
>    552			return lrng_drng_write_common((const char __user *)p, 
size,
>    553						      ent_count_bits);
>    554		case RNDZAPENTCNT:
>    555		case RNDCLEARPOOL:
>    556			/* Clear the entropy pool counter. */
>    557			if (!capable(CAP_SYS_ADMIN))
>    558				return -EPERM;
>    559			lrng_pool_set_entropy(0);
>    560			return 0;
>    561		case RNDRESEEDCRNG:
>    562			/*
>    563			 * We leave the capability check here since it is 
present
>    564			 * in the upstream's RNG implementation. Yet, user 
space
>    565			 * can trigger a reseed as easy as writing into /dev/
random
>    566			 * or /dev/urandom where no privilege is needed.
>    567			 */
>    568			if (!capable(CAP_SYS_ADMIN))
>    569				return -EPERM;
>    570			/* Force a reseed of all DRNGs */
>    571			lrng_drng_force_reseed();
>    572			return 0;
>    573		default:
>    574			return -EINVAL;
>    575		}
>    576	}
>    577
>    578	static int lrng_fasync(int fd, struct file *filp, int on)
>    579	{
>    580		return fasync_helper(fd, filp, on, &fasync);
>    581	}
>    582
>    583	const struct file_operations random_fops = {
>    584		.read  = lrng_drng_read_block,
>    585		.write = lrng_drng_write,
> 
>  > 586		.poll  = lrng_random_poll,
> 
>    587		.unlocked_ioctl = lrng_ioctl,
>    588		.compat_ioctl = compat_ptr_ioctl,
>    589		.fasync = lrng_fasync,
>    590		.llseek = noop_llseek,
>    591	};
>    592
> 
> ---
> 0-DAY kernel test infrastructure                 Open Source Technology
> Center https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org Intel
> Corporation



Ciao
Stephan



^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v28 11/12] LRNG - add interface for gathering of raw entropy
  2020-01-16  0:18           ` Randy Dunlap
@ 2020-01-16  6:43             ` Stephan Mueller
  2020-01-16  6:48               ` Randy Dunlap
  0 siblings, 1 reply; 162+ messages in thread
From: Stephan Mueller @ 2020-01-16  6:43 UTC (permalink / raw)
  To: Randy Dunlap
  Cc: Arnd Bergmann, Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Julia Lawall, Dan Carpenter

Am Donnerstag, 16. Januar 2020, 01:18:18 CET schrieb Randy Dunlap:

Hi Randy,

> On 1/15/20 2:35 AM, Stephan Müller wrote:
> > CC: "Eric W. Biederman" <ebiederm@xmission.com>
> > CC: "Alexander E. Patrakov" <patrakov@gmail.com>
> > CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
> > CC: "Theodore Y. Ts'o" <tytso@mit.edu>
> > CC: Willy Tarreau <w@1wt.eu>
> > CC: Matthew Garrett <mjg59@srcf.ucam.org>
> > CC: Vito Caputo <vcaputo@pengaru.com>
> > CC: Andreas Dilger <adilger.kernel@dilger.ca>
> > CC: Jan Kara <jack@suse.cz>
> > CC: Ray Strode <rstrode@redhat.com>
> > CC: William Jon McCann <mccann@jhu.edu>
> > CC: zhangjs <zachary@baishancloud.com>
> > CC: Andy Lutomirski <luto@kernel.org>
> > CC: Florian Weimer <fweimer@redhat.com>
> > CC: Lennart Poettering <mzxreary@0pointer.de>
> > CC: Nicolai Stange <nstange@suse.de>
> > Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
> > Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
> > Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
> > Tested-by: Neil Horman <nhorman@redhat.com>
> > Signed-off-by: Stephan Mueller <smueller@chronox.de>
> > ---
> > 
> >  drivers/char/lrng/Kconfig        |  16 ++
> >  drivers/char/lrng/Makefile       |   1 +
> >  drivers/char/lrng/lrng_testing.c | 271 +++++++++++++++++++++++++++++++
> >  3 files changed, 288 insertions(+)
> >  create mode 100644 drivers/char/lrng/lrng_testing.c
> > 
> > diff --git a/drivers/char/lrng/lrng_testing.c
> > b/drivers/char/lrng/lrng_testing.c new file mode 100644
> > index 000000000000..0e287eccd622
> > --- /dev/null
> > +++ b/drivers/char/lrng/lrng_testing.c
> > @@ -0,0 +1,271 @@
> > +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
> > +/*
> > + * Linux Random Number Generator (LRNG) Raw entropy collection tool
> > + *
> > + * Copyright (C) 2019 - 2020, Stephan Mueller <smueller@chronox.de>
> > + */
> > +
> > +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> > +
> > +#include <linux/atomic.h>
> > +#include <linux/bug.h>
> > +#include <linux/debugfs.h>
> > +#include <linux/module.h>
> > +#include <linux/sched.h>
> > +#include <linux/sched/signal.h>
> > +#include <linux/slab.h>
> > +#include <linux/string.h>
> > +#include <linux/types.h>
> > +#include <linux/uaccess.h>
> > +#include <linux/workqueue.h>
> > +#include <asm/errno.h>
> > +
> > +#include "lrng_internal.h"
> > +
> > +#define LRNG_TESTING_RINGBUFFER_SIZE	1024
> > +#define LRNG_TESTING_RINGBUFFER_MASK	(LRNG_TESTING_RINGBUFFER_SIZE - 1)
> > +
> > +static u32 lrng_testing_rb[LRNG_TESTING_RINGBUFFER_SIZE];
> > +static u32 lrng_rb_reader = 0;
> > +static u32 lrng_rb_writer = 0;
> > +static atomic_t lrng_testing_enabled = ATOMIC_INIT(0);
> > +
> > +static DECLARE_WAIT_QUEUE_HEAD(lrng_raw_read_wait);
> > +static DEFINE_SPINLOCK(lrng_raw_lock);
> > +
> > +/*
> > + * 0 ==> No boot test, gathering of runtime data allowed
> > + * 1 ==> Boot test enabled and ready for collecting data, gathering
> > runtime + *	 data is disabled
> > + * 2 ==> Boot test completed and disabled, gathering of runtime data is
> > + *	 disabled
> > + */
> > +static u32 boot_test = 0;
> > +module_param(boot_test, uint, 0644);
> > +MODULE_PARM_DESC(boot_test, "Enable gathering boot time entropy of the
> > first" +			    " entropy events");
> 
> One line for the string, please.

may I ask the question whether this should be done for all lines with printk 
statements? As checkpatch.pl will complain if you have lines larger than 80 
chars and complains about line-broken printk statements, I am always unsure 
which way to go.

All printk statements in the patch series have line-broken printk statements.

Ciao
Stephan



^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v28 11/12] LRNG - add interface for gathering of raw entropy
  2020-01-16  6:43             ` Stephan Mueller
@ 2020-01-16  6:48               ` Randy Dunlap
  2020-01-16  6:52                 ` Stephan Mueller
  0 siblings, 1 reply; 162+ messages in thread
From: Randy Dunlap @ 2020-01-16  6:48 UTC (permalink / raw)
  To: Stephan Mueller
  Cc: Arnd Bergmann, Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Julia Lawall, Dan Carpenter

On 1/15/20 10:43 PM, Stephan Mueller wrote:
> Am Donnerstag, 16. Januar 2020, 01:18:18 CET schrieb Randy Dunlap:
> 
> Hi Randy,
> 
>> On 1/15/20 2:35 AM, Stephan Müller wrote:
>>> CC: "Eric W. Biederman" <ebiederm@xmission.com>
>>> CC: "Alexander E. Patrakov" <patrakov@gmail.com>
>>> CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
>>> CC: "Theodore Y. Ts'o" <tytso@mit.edu>
>>> CC: Willy Tarreau <w@1wt.eu>
>>> CC: Matthew Garrett <mjg59@srcf.ucam.org>
>>> CC: Vito Caputo <vcaputo@pengaru.com>
>>> CC: Andreas Dilger <adilger.kernel@dilger.ca>
>>> CC: Jan Kara <jack@suse.cz>
>>> CC: Ray Strode <rstrode@redhat.com>
>>> CC: William Jon McCann <mccann@jhu.edu>
>>> CC: zhangjs <zachary@baishancloud.com>
>>> CC: Andy Lutomirski <luto@kernel.org>
>>> CC: Florian Weimer <fweimer@redhat.com>
>>> CC: Lennart Poettering <mzxreary@0pointer.de>
>>> CC: Nicolai Stange <nstange@suse.de>
>>> Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
>>> Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
>>> Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
>>> Tested-by: Neil Horman <nhorman@redhat.com>
>>> Signed-off-by: Stephan Mueller <smueller@chronox.de>
>>> ---
>>>
>>>  drivers/char/lrng/Kconfig        |  16 ++
>>>  drivers/char/lrng/Makefile       |   1 +
>>>  drivers/char/lrng/lrng_testing.c | 271 +++++++++++++++++++++++++++++++
>>>  3 files changed, 288 insertions(+)
>>>  create mode 100644 drivers/char/lrng/lrng_testing.c
>>>
>>> diff --git a/drivers/char/lrng/lrng_testing.c
>>> b/drivers/char/lrng/lrng_testing.c new file mode 100644
>>> index 000000000000..0e287eccd622
>>> --- /dev/null
>>> +++ b/drivers/char/lrng/lrng_testing.c
>>> @@ -0,0 +1,271 @@
>>> +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
>>> +/*
>>> + * Linux Random Number Generator (LRNG) Raw entropy collection tool
>>> + *
>>> + * Copyright (C) 2019 - 2020, Stephan Mueller <smueller@chronox.de>
>>> + */
>>> +
>>> +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
>>> +
>>> +#include <linux/atomic.h>
>>> +#include <linux/bug.h>
>>> +#include <linux/debugfs.h>
>>> +#include <linux/module.h>
>>> +#include <linux/sched.h>
>>> +#include <linux/sched/signal.h>
>>> +#include <linux/slab.h>
>>> +#include <linux/string.h>
>>> +#include <linux/types.h>
>>> +#include <linux/uaccess.h>
>>> +#include <linux/workqueue.h>
>>> +#include <asm/errno.h>
>>> +
>>> +#include "lrng_internal.h"
>>> +
>>> +#define LRNG_TESTING_RINGBUFFER_SIZE	1024
>>> +#define LRNG_TESTING_RINGBUFFER_MASK	(LRNG_TESTING_RINGBUFFER_SIZE - 1)
>>> +
>>> +static u32 lrng_testing_rb[LRNG_TESTING_RINGBUFFER_SIZE];
>>> +static u32 lrng_rb_reader = 0;
>>> +static u32 lrng_rb_writer = 0;
>>> +static atomic_t lrng_testing_enabled = ATOMIC_INIT(0);
>>> +
>>> +static DECLARE_WAIT_QUEUE_HEAD(lrng_raw_read_wait);
>>> +static DEFINE_SPINLOCK(lrng_raw_lock);
>>> +
>>> +/*
>>> + * 0 ==> No boot test, gathering of runtime data allowed
>>> + * 1 ==> Boot test enabled and ready for collecting data, gathering
>>> runtime + *	 data is disabled
>>> + * 2 ==> Boot test completed and disabled, gathering of runtime data is
>>> + *	 disabled
>>> + */
>>> +static u32 boot_test = 0;
>>> +module_param(boot_test, uint, 0644);
>>> +MODULE_PARM_DESC(boot_test, "Enable gathering boot time entropy of the
>>> first" +			    " entropy events");
>>
>> One line for the string, please.
> 
> may I ask the question whether this should be done for all lines with printk 
> statements? As checkpatch.pl will complain if you have lines larger than 80 
> chars and complains about line-broken printk statements, I am always unsure 
> which way to go.
> 
> All printk statements in the patch series have line-broken printk statements.

It's for grep-ability of the strings.
grepping for partial strings would work as is, but then one would need to know
what partial string to search for.

-- 
~Randy


^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v28 09/12] LRNG - add Jitter RNG fast noise source
  2020-01-16  0:17           ` Randy Dunlap
@ 2020-01-16  6:51             ` Stephan Mueller
  0 siblings, 0 replies; 162+ messages in thread
From: Stephan Mueller @ 2020-01-16  6:51 UTC (permalink / raw)
  To: Randy Dunlap
  Cc: Arnd Bergmann, Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Julia Lawall, Dan Carpenter

Am Donnerstag, 16. Januar 2020, 01:17:05 CET schrieb Randy Dunlap:

Hi Randy,

> On 1/15/20 2:34 AM, Stephan Müller wrote:
> > CC: "Eric W. Biederman" <ebiederm@xmission.com>
> > CC: "Alexander E. Patrakov" <patrakov@gmail.com>
> > CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
> > CC: "Theodore Y. Ts'o" <tytso@mit.edu>
> > CC: Willy Tarreau <w@1wt.eu>
> > CC: Matthew Garrett <mjg59@srcf.ucam.org>
> > CC: Vito Caputo <vcaputo@pengaru.com>
> > CC: Andreas Dilger <adilger.kernel@dilger.ca>
> > CC: Jan Kara <jack@suse.cz>
> > CC: Ray Strode <rstrode@redhat.com>
> > CC: William Jon McCann <mccann@jhu.edu>
> > CC: zhangjs <zachary@baishancloud.com>
> > CC: Andy Lutomirski <luto@kernel.org>
> > CC: Florian Weimer <fweimer@redhat.com>
> > CC: Lennart Poettering <mzxreary@0pointer.de>
> > CC: Nicolai Stange <nstange@suse.de>
> > Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
> > Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
> > Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
> > Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
> > Tested-by: Neil Horman <nhorman@redhat.com>
> > Signed-off-by: Stephan Mueller <smueller@chronox.de>
> > ---
> > 
> >  drivers/char/lrng/Kconfig     | 11 +++++
> >  drivers/char/lrng/Makefile    |  1 +
> >  drivers/char/lrng/lrng_jent.c | 89 +++++++++++++++++++++++++++++++++++
> >  3 files changed, 101 insertions(+)
> >  create mode 100644 drivers/char/lrng/lrng_jent.c
> > 
> > diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
> > index 0d070a3897dd..10b7cbdb8c8e 100644
> > --- a/drivers/char/lrng/Kconfig
> > +++ b/drivers/char/lrng/Kconfig
> > @@ -92,4 +92,15 @@ config LRNG_KCAPI
> > 
> >  	  provided by the selected kernel crypto API RNG.
> >  
> >  endif # LRNG_DRNG_SWITCH
> > 
> > +config LRNG_JENT
> > +	bool "Enable Jitter RNG as LRNG Seed Source"
> > +	select CRYPTO_JITTERENTROPY
> 
> Don't select unless CRYPTO is already set/enabled.

I added "depends on 
> 
> > +	help
> > +	  The Linux RNG may use the Jitter RNG as noise source. Enabling
> > +	  this option enables the use of the Jitter RNG. Its default
> > +	  entropy level is 16 bits of entropy per 256 data bits delivered
> > +	  by the Jitter RNG. This entropy level can be changed at boot
> > +	  time or at runtime with the lrng_base.jitterrng configuration
> > +	  variable.
> > +
> > 
> >  endif # LRNG
> > 
> > diff --git a/drivers/char/lrng/lrng_jent.c b/drivers/char/lrng/lrng_jent.c
> > new file mode 100644
> > index 000000000000..ff0bbe2680c4
> > --- /dev/null
> > +++ b/drivers/char/lrng/lrng_jent.c
> > @@ -0,0 +1,89 @@
> > +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
> > +/*
> > + * LRNG Fast Noise Source: Jitter RNG
> > + *
> > + * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
> > + */
> > +
> > +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> > +
> > +#include <linux/types.h>
> > +#include <crypto/internal/jitterentropy.h>
> > +
> > +#include "lrng_internal.h"
> > +
> > +/*
> > + * Estimated entropy of data is a 16th of
> > LRNG_DRNG_SECURITY_STRENGTH_BITS. + * Albeit a full entropy assessment is
> > provided for the noise source indicating + * that it provides high
> > entropy rates and considering that it deactivates + * when it detects
> > insufficient hardware, the chosen under estimation of + * entropy is
> > considered to be acceptable to all reviewers.
> > + */
> > +static u32 jitterrng = LRNG_DRNG_SECURITY_STRENGTH_BITS>>4;
> > +module_param(jitterrng, uint, 0644);
> > +MODULE_PARM_DESC(jitterrng, "Entropy in bits of 256 data bits from Jitter
> > " +			    "RNG noise source");
> 
> One line for the string, please, not split to 2 lines.

Changed.

Thank you.

Ciao
Stephan



^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v28 11/12] LRNG - add interface for gathering of raw entropy
  2020-01-16  6:48               ` Randy Dunlap
@ 2020-01-16  6:52                 ` Stephan Mueller
  0 siblings, 0 replies; 162+ messages in thread
From: Stephan Mueller @ 2020-01-16  6:52 UTC (permalink / raw)
  To: Randy Dunlap
  Cc: Arnd Bergmann, Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Julia Lawall, Dan Carpenter

Am Donnerstag, 16. Januar 2020, 07:48:20 CET schrieb Randy Dunlap:

Hi Randy,

> On 1/15/20 10:43 PM, Stephan Mueller wrote:
> > Am Donnerstag, 16. Januar 2020, 01:18:18 CET schrieb Randy Dunlap:
> > 
> > Hi Randy,
> > 
> >> On 1/15/20 2:35 AM, Stephan Müller wrote:
> >>> CC: "Eric W. Biederman" <ebiederm@xmission.com>
> >>> CC: "Alexander E. Patrakov" <patrakov@gmail.com>
> >>> CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
> >>> CC: "Theodore Y. Ts'o" <tytso@mit.edu>
> >>> CC: Willy Tarreau <w@1wt.eu>
> >>> CC: Matthew Garrett <mjg59@srcf.ucam.org>
> >>> CC: Vito Caputo <vcaputo@pengaru.com>
> >>> CC: Andreas Dilger <adilger.kernel@dilger.ca>
> >>> CC: Jan Kara <jack@suse.cz>
> >>> CC: Ray Strode <rstrode@redhat.com>
> >>> CC: William Jon McCann <mccann@jhu.edu>
> >>> CC: zhangjs <zachary@baishancloud.com>
> >>> CC: Andy Lutomirski <luto@kernel.org>
> >>> CC: Florian Weimer <fweimer@redhat.com>
> >>> CC: Lennart Poettering <mzxreary@0pointer.de>
> >>> CC: Nicolai Stange <nstange@suse.de>
> >>> Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
> >>> Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
> >>> Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
> >>> Tested-by: Neil Horman <nhorman@redhat.com>
> >>> Signed-off-by: Stephan Mueller <smueller@chronox.de>
> >>> ---
> >>> 
> >>>  drivers/char/lrng/Kconfig        |  16 ++
> >>>  drivers/char/lrng/Makefile       |   1 +
> >>>  drivers/char/lrng/lrng_testing.c | 271 +++++++++++++++++++++++++++++++
> >>>  3 files changed, 288 insertions(+)
> >>>  create mode 100644 drivers/char/lrng/lrng_testing.c
> >>> 
> >>> diff --git a/drivers/char/lrng/lrng_testing.c
> >>> b/drivers/char/lrng/lrng_testing.c new file mode 100644
> >>> index 000000000000..0e287eccd622
> >>> --- /dev/null
> >>> +++ b/drivers/char/lrng/lrng_testing.c
> >>> @@ -0,0 +1,271 @@
> >>> +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
> >>> +/*
> >>> + * Linux Random Number Generator (LRNG) Raw entropy collection tool
> >>> + *
> >>> + * Copyright (C) 2019 - 2020, Stephan Mueller <smueller@chronox.de>
> >>> + */
> >>> +
> >>> +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> >>> +
> >>> +#include <linux/atomic.h>
> >>> +#include <linux/bug.h>
> >>> +#include <linux/debugfs.h>
> >>> +#include <linux/module.h>
> >>> +#include <linux/sched.h>
> >>> +#include <linux/sched/signal.h>
> >>> +#include <linux/slab.h>
> >>> +#include <linux/string.h>
> >>> +#include <linux/types.h>
> >>> +#include <linux/uaccess.h>
> >>> +#include <linux/workqueue.h>
> >>> +#include <asm/errno.h>
> >>> +
> >>> +#include "lrng_internal.h"
> >>> +
> >>> +#define LRNG_TESTING_RINGBUFFER_SIZE	1024
> >>> +#define LRNG_TESTING_RINGBUFFER_MASK	
(LRNG_TESTING_RINGBUFFER_SIZE - 1)
> >>> +
> >>> +static u32 lrng_testing_rb[LRNG_TESTING_RINGBUFFER_SIZE];
> >>> +static u32 lrng_rb_reader = 0;
> >>> +static u32 lrng_rb_writer = 0;
> >>> +static atomic_t lrng_testing_enabled = ATOMIC_INIT(0);
> >>> +
> >>> +static DECLARE_WAIT_QUEUE_HEAD(lrng_raw_read_wait);
> >>> +static DEFINE_SPINLOCK(lrng_raw_lock);
> >>> +
> >>> +/*
> >>> + * 0 ==> No boot test, gathering of runtime data allowed
> >>> + * 1 ==> Boot test enabled and ready for collecting data, gathering
> >>> runtime + *	 data is disabled
> >>> + * 2 ==> Boot test completed and disabled, gathering of runtime data is
> >>> + *	 disabled
> >>> + */
> >>> +static u32 boot_test = 0;
> >>> +module_param(boot_test, uint, 0644);
> >>> +MODULE_PARM_DESC(boot_test, "Enable gathering boot time entropy of the
> >>> first" +			    " entropy events");
> >> 
> >> One line for the string, please.
> > 
> > may I ask the question whether this should be done for all lines with
> > printk statements? As checkpatch.pl will complain if you have lines
> > larger than 80 chars and complains about line-broken printk statements, I
> > am always unsure which way to go.
> > 
> > All printk statements in the patch series have line-broken printk
> > statements.
> It's for grep-ability of the strings.
> grepping for partial strings would work as is, but then one would need to
> know what partial string to search for.

Ok, I am changing all these strings to one-liners even though checkpatch.pl 
will complain.

Thank you.

Ciao
Stephan



^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v28 07/12] LRNG - add kernel crypto API PRNG extension
  2020-01-16  0:15           ` Randy Dunlap
@ 2020-01-16  6:54             ` Stephan Mueller
  0 siblings, 0 replies; 162+ messages in thread
From: Stephan Mueller @ 2020-01-16  6:54 UTC (permalink / raw)
  To: Randy Dunlap
  Cc: Arnd Bergmann, Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Julia Lawall, Dan Carpenter

Am Donnerstag, 16. Januar 2020, 01:15:46 CET schrieb Randy Dunlap:

Hi Randy,

> On 1/15/20 2:34 AM, Stephan Müller wrote:
> > CC: "Eric W. Biederman" <ebiederm@xmission.com>
> > CC: "Alexander E. Patrakov" <patrakov@gmail.com>
> > CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
> > CC: "Theodore Y. Ts'o" <tytso@mit.edu>
> > CC: Willy Tarreau <w@1wt.eu>
> > CC: Matthew Garrett <mjg59@srcf.ucam.org>
> > CC: Vito Caputo <vcaputo@pengaru.com>
> > CC: Andreas Dilger <adilger.kernel@dilger.ca>
> > CC: Jan Kara <jack@suse.cz>
> > CC: Ray Strode <rstrode@redhat.com>
> > CC: William Jon McCann <mccann@jhu.edu>
> > CC: zhangjs <zachary@baishancloud.com>
> > CC: Andy Lutomirski <luto@kernel.org>
> > CC: Florian Weimer <fweimer@redhat.com>
> > CC: Lennart Poettering <mzxreary@0pointer.de>
> > CC: Nicolai Stange <nstange@suse.de>
> > Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
> > Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
> > Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
> > Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
> > Tested-by: Neil Horman <nhorman@redhat.com>
> > Signed-off-by: Stephan Mueller <smueller@chronox.de>
> > ---
> > 
> >  drivers/char/lrng/Kconfig      |  10 +
> >  drivers/char/lrng/Makefile     |   1 +
> >  drivers/char/lrng/lrng_kcapi.c | 327 +++++++++++++++++++++++++++++++++
> >  3 files changed, 338 insertions(+)
> >  create mode 100644 drivers/char/lrng/lrng_kcapi.c
> > 
> > diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
> > index 15fb623d9d1f..0d070a3897dd 100644
> > --- a/drivers/char/lrng/Kconfig
> > +++ b/drivers/char/lrng/Kconfig
> > @@ -80,6 +80,16 @@ config LRNG_DRBG
> > 
> >  	  Enable the SP800-90A DRBG support for the LRNG. Once the
> >  	  module is loaded, output from /dev/random, /dev/urandom,
> >  	  getrandom(2), or get_random_bytes is provided by a DRBG.
> > 
> > +
> > +config LRNG_KCAPI
> > +	tristate "Kernel Crypto API support for the LRNG"
> > +	select CRYPTO_RNG
> 
> Don't select CRYPTO_RNG unless you know that CRYPTO is set/enabled.

I added "depends on CRYPTO"
> 
> > +	help
> > +	  Enable the support for generic pseudo-random number
> > +	  generators offered by the kernel crypto API with the
> > +	  LRNG. Once the module is loaded, output from /dev/random,
> > +	  /dev/urandom, getrandom(2), or get_random_bytes is
> > +	  provided by the selected kernel crypto API RNG.
> > 
> >  endif # LRNG_DRNG_SWITCH
> >  
> >  endif # LRNG

Thank you.

Ciao
Stephan



^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v28 06/12] LRNG - add SP800-90A DRBG extension
  2020-01-16  0:14           ` Randy Dunlap
@ 2020-01-16  6:55             ` Stephan Mueller
  0 siblings, 0 replies; 162+ messages in thread
From: Stephan Mueller @ 2020-01-16  6:55 UTC (permalink / raw)
  To: Randy Dunlap
  Cc: Arnd Bergmann, Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Julia Lawall, Dan Carpenter

Am Donnerstag, 16. Januar 2020, 01:14:35 CET schrieb Randy Dunlap:

Hi Randy,

> On 1/15/20 2:33 AM, Stephan Müller wrote:
> > CC: "Eric W. Biederman" <ebiederm@xmission.com>
> > CC: "Alexander E. Patrakov" <patrakov@gmail.com>
> > CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
> > CC: "Theodore Y. Ts'o" <tytso@mit.edu>
> > CC: Willy Tarreau <w@1wt.eu>
> > CC: Matthew Garrett <mjg59@srcf.ucam.org>
> > CC: Vito Caputo <vcaputo@pengaru.com>
> > CC: Andreas Dilger <adilger.kernel@dilger.ca>
> > CC: Jan Kara <jack@suse.cz>
> > CC: Ray Strode <rstrode@redhat.com>
> > CC: William Jon McCann <mccann@jhu.edu>
> > CC: zhangjs <zachary@baishancloud.com>
> > CC: Andy Lutomirski <luto@kernel.org>
> > CC: Florian Weimer <fweimer@redhat.com>
> > CC: Lennart Poettering <mzxreary@0pointer.de>
> > CC: Nicolai Stange <nstange@suse.de>
> > Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
> > Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
> > Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
> > Tested-by: Neil Horman <nhorman@redhat.com>
> > Signed-off-by: Stephan Mueller <smueller@chronox.de>
> > ---
> > 
> >  drivers/char/lrng/Kconfig     |  11 ++
> >  drivers/char/lrng/Makefile    |   1 +
> >  drivers/char/lrng/lrng_drbg.c | 260 ++++++++++++++++++++++++++++++++++
> >  3 files changed, 272 insertions(+)
> >  create mode 100644 drivers/char/lrng/lrng_drbg.c
> > 
> > diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
> > index cb701bb0b8b6..15fb623d9d1f 100644
> > --- a/drivers/char/lrng/Kconfig
> > +++ b/drivers/char/lrng/Kconfig
> > @@ -71,4 +71,15 @@ menuconfig LRNG_DRNG_SWITCH
> > 
> >  	  accessible via the external interfaces. With this configuration
> >  	  option other DRNGs can be selected and loaded at runtime.
> > 
> > +if LRNG_DRNG_SWITCH
> > +config LRNG_DRBG
> > +	tristate "SP800-90A support for the LRNG"
> > +	select CRYPTO_DRBG_MENU
> > +	select CRYPTO_CMAC if CRYPTO_DRBG_CTR
> 
> Don't select these if CRYPTO is not already set/enabled.
> It causes Kconfig warnings and possible build errors.

I added "depends on CRYPTO"
> 
> > +	help
> > +	  Enable the SP800-90A DRBG support for the LRNG. Once the
> > +	  module is loaded, output from /dev/random, /dev/urandom,
> > +	  getrandom(2), or get_random_bytes is provided by a DRBG.
> > +endif # LRNG_DRNG_SWITCH
> > +
> > 
> >  endif # LRNG
> > 
> > diff --git a/drivers/char/lrng/lrng_drbg.c b/drivers/char/lrng/lrng_drbg.c
> > new file mode 100644
> > index 000000000000..8bf2badb1fe0
> > --- /dev/null
> > +++ b/drivers/char/lrng/lrng_drbg.c
> > @@ -0,0 +1,260 @@
> > +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
> > +/*
> > + * Backend for the LRNG providing the cryptographic primitives using the
> > + * kernel crypto API and its DRBG.
> > + *
> > + * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
> > + */
> > +
> > +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> > +
> > +#include <crypto/drbg.h>
> > +#include <linux/init.h>
> > +#include <linux/module.h>
> > +#include <linux/lrng.h>
> > +
> > +/*
> > + * Define a DRBG plus a hash / MAC used to extract data from the entropy
> > pool. + * For LRNG_HASH_NAME you can use a hash or a MAC (HMAC or CMAC)
> > of your choice + * (Note, you should use the suggested selections below
> > -- using SHA-1 or MD5 + * is not wise). The idea is that the used cipher
> > primitive can be selected to + * be the same as used for the DRBG. I.e.
> > the LRNG only uses one cipher + * primitive using the same cipher
> > implementation with the options offered in + * the following. This means,
> > if the CTR DRBG is selected and AES-NI is present, + * both the CTR DRBG
> > and the selected cmac(aes) use AES-NI.
> > + *
> > + * The security strengths of the DRBGs are all 256 bits according to
> > + * SP800-57 section 5.6.1.
> > + *
> > + * This definition is allowed to be changed.
> > + */
> > +#ifdef CONFIG_CRYPTO_DRBG_CTR
> > +static unsigned int lrng_drbg_type = 0;
> > +#elif defined CONFIG_CRYPTO_DRBG_HMAC
> > +static unsigned int lrng_drbg_type = 1;
> > +#elif defined CONFIG_CRYPTO_DRBG_HASH
> > +static unsigned int lrng_drbg_type = 2;
> > +#else
> > +#error "Unknown DRBG in use"
> > +#endif
> > +
> > +/* The parameter must be r/o in sysfs as otherwise races appear. */
> > +module_param(lrng_drbg_type, uint, 0444);
> > +MODULE_PARM_DESC(lrng_drbg_type, "DRBG type used for LRNG (0->CTR_DRBG, "
> > +				 "1->HMAC_DRBG, 2->Hash_DRBG)");
> 
> One line for the string, please, not split.

Changed

Thank you.

Ciao
Stephan



^ permalink raw reply	[flat|nested] 162+ messages in thread

* Re: [PATCH v28 01/12] Linux Random Number Generator
  2020-01-16  0:11           ` Randy Dunlap
@ 2020-01-16  7:22             ` Stephan Mueller
  0 siblings, 0 replies; 162+ messages in thread
From: Stephan Mueller @ 2020-01-16  7:22 UTC (permalink / raw)
  To: Randy Dunlap
  Cc: Arnd Bergmann, Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Julia Lawall, Dan Carpenter

Am Donnerstag, 16. Januar 2020, 01:11:40 CET schrieb Randy Dunlap:

Hi Randy,

> Hi,
> 
> On 1/15/20 2:31 AM, Stephan Müller wrote:
> > CC: "Eric W. Biederman" <ebiederm@xmission.com>
> > CC: "Alexander E. Patrakov" <patrakov@gmail.com>
> > CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
> > CC: "Theodore Y. Ts'o" <tytso@mit.edu>
> > CC: Willy Tarreau <w@1wt.eu>
> > CC: Matthew Garrett <mjg59@srcf.ucam.org>
> > CC: Vito Caputo <vcaputo@pengaru.com>
> > CC: Andreas Dilger <adilger.kernel@dilger.ca>
> > CC: Jan Kara <jack@suse.cz>
> > CC: Ray Strode <rstrode@redhat.com>
> > CC: William Jon McCann <mccann@jhu.edu>
> > CC: zhangjs <zachary@baishancloud.com>
> > CC: Andy Lutomirski <luto@kernel.org>
> > CC: Florian Weimer <fweimer@redhat.com>
> > CC: Lennart Poettering <mzxreary@0pointer.de>
> > CC: Nicolai Stange <nstange@suse.de>
> > Mathematical aspects Reviewed-by: "Peter, Matthias"
> > <matthias.peter@bsi.bund.de> Reviewed-by: Marcelo Henrique Cerri
> > <marcelo.cerri@canonical.com>
> > Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
> > Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
> > Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
> > Tested-by: Neil Horman <nhorman@redhat.com>
> > Signed-off-by: Stephan Mueller <smueller@chronox.de>
> > ---
> > 
> >  MAINTAINERS                         |   7 +
> >  drivers/char/Kconfig                |   2 +
> >  drivers/char/Makefile               |   9 +-
> >  drivers/char/lrng/Kconfig           |  67 +++
> >  drivers/char/lrng/Makefile          |   9 +
> >  drivers/char/lrng/lrng_archrandom.c |  94 ++++
> >  drivers/char/lrng/lrng_aux.c        | 148 +++++++
> >  drivers/char/lrng/lrng_chacha20.c   | 265 ++++++++++++
> >  drivers/char/lrng/lrng_chacha20.h   |  25 ++
> >  drivers/char/lrng/lrng_drng.c       | 400 +++++++++++++++++
> >  drivers/char/lrng/lrng_interfaces.c | 638 ++++++++++++++++++++++++++++
> >  drivers/char/lrng/lrng_internal.h   | 296 +++++++++++++
> >  drivers/char/lrng/lrng_lfsr.h       | 152 +++++++
> >  drivers/char/lrng/lrng_pool.c       | 588 +++++++++++++++++++++++++
> >  drivers/char/lrng/lrng_sw_noise.c   | 102 +++++
> >  drivers/char/lrng/lrng_sw_noise.h   |  57 +++
> >  include/linux/lrng.h                |  63 +++
> >  17 files changed, 2921 insertions(+), 1 deletion(-)
> >  create mode 100644 drivers/char/lrng/Kconfig
> >  create mode 100644 drivers/char/lrng/Makefile
> >  create mode 100644 drivers/char/lrng/lrng_archrandom.c
> >  create mode 100644 drivers/char/lrng/lrng_aux.c
> >  create mode 100644 drivers/char/lrng/lrng_chacha20.c
> >  create mode 100644 drivers/char/lrng/lrng_chacha20.h
> >  create mode 100644 drivers/char/lrng/lrng_drng.c
> >  create mode 100644 drivers/char/lrng/lrng_interfaces.c
> >  create mode 100644 drivers/char/lrng/lrng_internal.h
> >  create mode 100644 drivers/char/lrng/lrng_lfsr.h
> >  create mode 100644 drivers/char/lrng/lrng_pool.c
> >  create mode 100644 drivers/char/lrng/lrng_sw_noise.c
> >  create mode 100644 drivers/char/lrng/lrng_sw_noise.h
> >  create mode 100644 include/linux/lrng.h
> > 
> > diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
> > new file mode 100644
> > index 000000000000..56f13efd3592
> > --- /dev/null
> > +++ b/drivers/char/lrng/Kconfig
> > @@ -0,0 +1,67 @@
> > +# SPDX-License-Identifier: GPL-2.0
> > +#
> > +# Linux Random Number Generator configuration
> > +#
> > +
> > +menuconfig LRNG
> > +	bool "Linux Random Number Generator"
> 
> This should probably depend on CRYPTO and/or some other CRYPTO_xxx symbols.
> Or (worst case) select them.  :(

It does not - all CRYPTO related code is limited into the lrng_drbg.c, 
lrng_kcapi.c and lrng_jent.c which are all guarded by a Kconfig option.
> 
> This message (when CONFIG_CRYPTO is disabled and no crypto facilities are
> enabled) should be avoidable when the correct Kconfig entries are used:
> 
> ../drivers/char/lrng/lrng_drbg.c:38:2: error: #error "Unknown DRBG in use"
>  #error "Unknown DRBG in use"

Right - this should now be fixed with a depends on CRYPTO for the 
aforementioned 3 C files which have an equal entry in Kconfig.
> 
> > +	help
> > +	  The Linux Random Number Generator (LRNG) is the replacement
> > +	  of the existing /dev/random provided with drivers/char/random.c.
> > +	  It generates entropy from different noise sources and
> > +	  delivers significant entropy during boot.
> > +
> > +if LRNG
> > +
> > +choice
> > +	prompt "LRNG Entropy Pool Size"
> > +	default LRNG_POOL_SIZE_4096
> > +	help
> > +	  Select the size of the LRNG entropy pool. The size of the
> > +	  entropy pool is relevant for the amount of entropy that
> > +	  the LRNG can maintain as a maximum. The larger the size
> > +	  of the entropy pool is the more entropy can be maintained
> > +	  but the less often older entropic values are overwritten
> > +	  with new entropy.
> > +
> > +	config LRNG_POOL_SIZE_512
> > +		bool "512 bits"
> > +
> > +	config LRNG_POOL_SIZE_1024
> > +		bool "1024 bits"
> > +
> > +	config LRNG_POOL_SIZE_2048
> > +		bool "2048 bits"
> > +
> > +	config LRNG_POOL_SIZE_4096
> > +		bool "4096 bits (default)"
> > +
> > +	config LRNG_POOL_SIZE_8192
> > +		bool "8192 bits"
> > +
> > +	config LRNG_POOL_SIZE_16384
> > +		bool "16384 bits"
> > +
> > +	config LRNG_POOL_SIZE_32768
> > +		bool "32768 bits"
> > +
> > +	config LRNG_POOL_SIZE_65536
> > +		bool "65536 bits"
> > +
> > +	config LRNG_POOL_SIZE_131072
> > +		bool "131072 bits"
> > +endchoice
> > +
> > +config LRNG_POOL_SIZE
> > +	int
> > +	default 0 if LRNG_POOL_SIZE_512
> > +	default 1 if LRNG_POOL_SIZE_1024
> > +	default 2 if LRNG_POOL_SIZE_2048
> > +	default 3 if LRNG_POOL_SIZE_4096
> > +	default 4 if LRNG_POOL_SIZE_8192
> > +	default 5 if LRNG_POOL_SIZE_16384
> > +	default 6 if LRNG_POOL_SIZE_32768
> > +	default 7 if LRNG_POOL_SIZE_65536
> > +	default 8 if LRNG_POOL_SIZE_131072
> > +
> > +endif # LRNG
> > 
> > diff --git a/drivers/char/lrng/lrng_archrandom.c
> > b/drivers/char/lrng/lrng_archrandom.c new file mode 100644
> > index 000000000000..eeba708d025f
> > --- /dev/null
> > +++ b/drivers/char/lrng/lrng_archrandom.c
> > @@ -0,0 +1,94 @@
> > +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
> > +/*
> > + * LRNG Fast Noise Source: CPU-based noise source
> > + *
> > + * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
> > + */
> > +
> > +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> > +
> > +#include <linux/random.h>
> > +
> > +#include "lrng_internal.h"
> > +
> > +/*
> > + * Estimated entropy of data is a 32th of
> > LRNG_DRNG_SECURITY_STRENGTH_BITS. + * As we have no ability to review the
> > implementation of those noise sources, + * it is prudent to have a
> > conservative estimate here.
> > + */
> > +#define LRNG_ARCHRANDOM_DEFAULT_STRENGTH
> > (LRNG_DRNG_SECURITY_STRENGTH_BITS>>5) +#define
> > LRNG_ARCHRANDOM_TRUST_CPU_STRENGTH LRNG_DRNG_SECURITY_STRENGTH_BITS
> > +#ifdef CONFIG_RANDOM_TRUST_CPU
> > +static u32 archrandom = LRNG_ARCHRANDOM_TRUST_CPU_STRENGTH;
> > +#else
> > +static u32 archrandom = LRNG_ARCHRANDOM_DEFAULT_STRENGTH;
> > +#endif
> > +module_param(archrandom, uint, 0644);
> > +MODULE_PARM_DESC(archrandom, "Entropy in bits of 256 data bits from CPU
> > noise " +			     "source (e.g. RDRAND)");
> 
> Please put the string on one line like several other MODULE_PARM_DESC() are
> done:
> 
> +MODULE_PARM_DESC(archrandom,
> +		"Entropy in bits of 256 data bits from CPU noise source (e.g. 
RDRAND)");

Done.
> 
> 
> With CONFIG_CRYPTO disabled, these warnings happen:
> 
> WARNING: unmet direct dependencies detected for CRYPTO_DRBG_MENU
>   Depends on [n]: CRYPTO [=n]
>   Selected by [m]:
>   - LRNG_DRBG [=m] && LRNG [=y] && LRNG_DRNG_SWITCH [=y]
> 
> WARNING: unmet direct dependencies detected for CRYPTO_RNG
>   Depends on [n]: CRYPTO [=n]
>   Selected by [m]:
>   - LRNG_KCAPI [=m] && LRNG [=y] && LRNG_DRNG_SWITCH [=y]
> 
> ../drivers/char/lrng/lrng_drbg.c: In function ‘lrng_hash_name’:
> ../drivers/char/lrng/lrng_drbg.c:225:1: warning: control reaches end of
> non-void function [-Wreturn-type] }
>  ^
> ../drivers/char/lrng/lrng_drbg.c: In function ‘lrng_drbg_name’:
> ../drivers/char/lrng/lrng_drbg.c:220:1: warning: control reaches end of
> non-void function [-Wreturn-type] }
>  ^
> 
> and build errors happen also, which can be prevented with Kconfig fixes.

With the changes to the Kconfig file as explained in the other emails, I can 
successfully compile the LRNG without the crypto API being enabled.

Thank you for pointing that one out.

Ciao
Stephan



^ permalink raw reply	[flat|nested] 162+ messages in thread

* [PATCH v29 00/12] /dev/random - a new approach with full SP800-90B
  2020-01-15 10:31       ` [PATCH v28 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                           ` (11 preceding siblings ...)
  2020-01-15 10:36         ` [PATCH v28 12/12] LRNG - add power-on and runtime self-tests Stephan Müller
@ 2020-01-19 21:12         ` Stephan Müller
  2020-01-19 21:13           ` [PATCH v29 01/12] Linux Random Number Generator Stephan Müller
                             ` (11 more replies)
  12 siblings, 12 replies; 162+ messages in thread
From: Stephan Müller @ 2020-01-19 21:12 UTC (permalink / raw)
  To: Stephan Müller
  Cc: Arnd Bergmann, Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap, Julia Lawall, Dan Carpenter

Hi,

The following patch set provides a different approach to /dev/random which is
called Linux Random Number Generator (LRNG) to collect entropy within the Linux
kernel. The main improvements compared to the existing /dev/random is to provide
sufficient entropy during boot time as well as in virtual environments and when
using SSDs. A secondary design goal is to limit the impact of the entropy
collection on massive parallel systems and also allow the use accelerated
cryptographic primitives. Also, all steps of the entropic data processing are
testable.

The LRNG patch set allows a user to select use of the existing /dev/random or
the LRNG during compile time. As the LRNG provides API and ABI compatible
interfaces to the existing /dev/random implementation, the user can freely chose
the RNG implementation without affecting kernel or user space operations.

This patch set provides early boot-time entropy which implies that no
additional flags to the getrandom(2) system call discussed recently on
the LKML is considered to be necessary. Yet, if additional flags are
introduced to cover special hardware, the LRNG implementation will also
provide them to be fully ABI and API compliant as already discussed on
LKML.

The LRNG is fully compliant to SP800-90B requirements and is shipped with a
full SP800-90B assessment and all required test tools. The existing /dev/random
implementation on the other hand has architectural limitations which
does not easily allow to bring the implementation in compliance with
SP800-90B. The key statement that causes concern is SP800-90B section
3.1.6. This section denies crediting entropy to multiple similar noise
sources. This section explicitly references different noise sources resting
on the timing of events and their derivatives (i.e. it is a direct complaint
to the existing existing /dev/random implementation). Therefore, SP800-90B
now denies the very issue mentioned in [1] with the existing /dev/random
implementation for a long time: crediting entropy to interrupts as well as
crediting entropy to derivatives of interrupts (HID and disk events). This is
not permissible with SP800-90B.

SP800-90B specifies various requirements for the noise source(s) that seed any
DRNG including SP800-90A DRBGs. In about a year from now, SP800-90B will be
mandated for all noise sources that provide entropy to DRBGs as part of a FIPS
140-[2|3] validation or other evaluation types. That means, if we there are no
solutions to comply with the requirements of SP800-90B found till one year
from now, any random number generation and ciphers based on random numbers
on Linux will be considered and treated as not applicable and delivering
no entropy! As /dev/urandom, getrandom(2) and /dev/random are the most
common and prevalent noise sources for DRNGs, all these DRNGs are affected.
This applies across the board for all validations of cryptography executing on
Linux (kernel and user space modules).

For users that are not interested in SP800-90B, the entire code for the
compliance as well as test interfaces can be deselected at compile time.

The design and implementation is driven by a set of goals described in [1]
that the LRNG completely implements. Furthermore, [1] includes the full
assessment of the SP800-90B compliance as well as a comparison with RNG
design suggestions of SP800-90C, and AIS20/31.

The LRNG provides a complete separation of the noise source maintenance
and the collection of entropy into an entropy pool from the post-processing
using a pseudo-random number generator. Different DRNGs are supported,
including:

* The LRNG can be compile-time enabled to replace the existing /dev/random
  implementation. When not selecting the LRNG at compile time (default), the
  existing /dev/random implementation is built.

* Built-in ChaCha20 DRNG which has no dependency to other kernel
  frameworks.

* SP800-90A DRBG using the kernel crypto API including its accelerated
  raw cipher implementations. This implies that the output of /dev/random,
  getrandom(2), /dev/urandom or get_random_bytes is fully compliant to
  SP800-90A.

* Arbitrary DRNGs registered with the kernel crypto API

* Full compliance with SP800-90B which covers the startup and runtime health
  tests mandated by SP800-90B as well as providing the test tools and test
  interfaces to obtain raw noise data securely. The test tools are provided at
  [1].

Booting the patch with the kernel command line option
"dyndbg=file drivers/char/lrng/* +p" generates logs indicating the operation
of the LRNG. Each log is pre-pended with "lrng".

The LRNG has a flexible design by allowing an easy replacement of the
deterministic random number generator component.

Compared to the existing /dev/random implementation, the compiled binary
is smaller when the LRNG is compiled with all options equal to the
existing /dev/random (i.e. only CONFIG_LRNG is set): random.o is 52.5 kBytes
whereas all LRNG object files are in 49 kBytes in size. The fully
SP800-90A/SP800-90B compliant binary code (CONFIG_LRNG,
CONFIG_LRNG_DRNG_SWITCH, CONFIG_LRNG_DRBG, CONFIG_LRNG_HEALTH_TESTS)
uses some 61 kBytes. In addition, the LRNG is about 50% faster in the
performance critical interrupt handler code path compared to the existing
/dev/random implementation.

[1] http://www.chronox.de/lrng.html - If the patch is accepted, I would
be volunteering to convert the documentation into RST format and
contribute it to the Linux kernel documentation directory.

Changes (compared to the previous patch set):

* All grep-able strings are placed on one line as requested by Randy
  Dunlap.

* Add "depend on CRYPTO" to CONFIG_LRNG_DRBG, CONFIG_LRNG_KCAPI,
  CONFIG_LRNG_JENT allowing the LRNG to be compiled without the kernel
  crypto API. A successful compilation of the LRNG with the remaining
  configure options was performed. Thanks to Randy Dunlap for
  pointing this out.

This patch requires the presence of patch
75551dbf112c992bc6c99a972990b3f272247e23 from Ted Tso's kernel tree
(specifically the addition of GRND_INSECURE to random.h)

As a side node: With the switchable DRNG support offered in this patch set,
the following areas could be removed. As the existing /dev/random has no support
for switchable DRNGs, however, this is not yet feasible though.

* remove lrng_ready_list and all code around it in lrng_interfaces.c

* remove the kernel crypto API RNG API to avoid having two random number
  providing APIs - this would imply that all RNGs developed for this API would
  be converted to the LRNG interface

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>

Stephan Mueller (12):
  Linux Random Number Generator
  LRNG - allocate one DRNG instance per NUMA node
  LRNG - sysctls and /proc interface
  LRNG - add switchable DRNG support
  crypto: DRBG - externalize DRBG functions for LRNG
  LRNG - add SP800-90A DRBG extension
  LRNG - add kernel crypto API PRNG extension
  crypto: provide access to a static Jitter RNG state
  LRNG - add Jitter RNG fast noise source
  LRNG - add SP800-90B compliant health tests
  LRNG - add interface for gathering of raw entropy
  LRNG - add power-on and runtime self-tests

 MAINTAINERS                                   |   7 +
 crypto/drbg.c                                 |  16 +-
 crypto/jitterentropy-kcapi.c                  |   3 +-
 crypto/jitterentropy.c                        |  25 +-
 drivers/char/Kconfig                          |   2 +
 drivers/char/Makefile                         |   9 +-
 drivers/char/lrng/Kconfig                     | 206 ++++++
 drivers/char/lrng/Makefile                    |  19 +
 drivers/char/lrng/lrng_archrandom.c           |  93 +++
 drivers/char/lrng/lrng_aux.c                  | 148 ++++
 drivers/char/lrng/lrng_chacha20.c             | 263 ++++++++
 drivers/char/lrng/lrng_chacha20.h             |  25 +
 drivers/char/lrng/lrng_drbg.c                 | 257 +++++++
 drivers/char/lrng/lrng_drng.c                 | 400 +++++++++++
 drivers/char/lrng/lrng_health.c               | 407 +++++++++++
 drivers/char/lrng/lrng_interfaces.c           | 635 ++++++++++++++++++
 drivers/char/lrng/lrng_internal.h             | 305 +++++++++
 drivers/char/lrng/lrng_jent.c                 |  88 +++
 drivers/char/lrng/lrng_kcapi.c                | 321 +++++++++
 drivers/char/lrng/lrng_lfsr.h                 | 152 +++++
 drivers/char/lrng/lrng_numa.c                 | 101 +++
 drivers/char/lrng/lrng_pool.c                 | 586 ++++++++++++++++
 drivers/char/lrng/lrng_proc.c                 | 163 +++++
 drivers/char/lrng/lrng_selftest.c             | 418 ++++++++++++
 drivers/char/lrng/lrng_sw_noise.c             | 102 +++
 drivers/char/lrng/lrng_sw_noise.h             |  57 ++
 drivers/char/lrng/lrng_switch.c               | 182 +++++
 drivers/char/lrng/lrng_testing.c              | 269 ++++++++
 include/crypto/drbg.h                         |   7 +
 .../crypto/internal}/jitterentropy.h          |   3 +
 include/linux/lrng.h                          |  63 ++
 31 files changed, 5322 insertions(+), 10 deletions(-)
 create mode 100644 drivers/char/lrng/Kconfig
 create mode 100644 drivers/char/lrng/Makefile
 create mode 100644 drivers/char/lrng/lrng_archrandom.c
 create mode 100644 drivers/char/lrng/lrng_aux.c
 create mode 100644 drivers/char/lrng/lrng_chacha20.c
 create mode 100644 drivers/char/lrng/lrng_chacha20.h
 create mode 100644 drivers/char/lrng/lrng_drbg.c
 create mode 100644 drivers/char/lrng/lrng_drng.c
 create mode 100644 drivers/char/lrng/lrng_health.c
 create mode 100644 drivers/char/lrng/lrng_interfaces.c
 create mode 100644 drivers/char/lrng/lrng_internal.h
 create mode 100644 drivers/char/lrng/lrng_jent.c
 create mode 100644 drivers/char/lrng/lrng_kcapi.c
 create mode 100644 drivers/char/lrng/lrng_lfsr.h
 create mode 100644 drivers/char/lrng/lrng_numa.c
 create mode 100644 drivers/char/lrng/lrng_pool.c
 create mode 100644 drivers/char/lrng/lrng_proc.c
 create mode 100644 drivers/char/lrng/lrng_selftest.c
 create mode 100644 drivers/char/lrng/lrng_sw_noise.c
 create mode 100644 drivers/char/lrng/lrng_sw_noise.h
 create mode 100644 drivers/char/lrng/lrng_switch.c
 create mode 100644 drivers/char/lrng/lrng_testing.c
 rename {crypto => include/crypto/internal}/jitterentropy.h (84%)
 create mode 100644 include/linux/lrng.h

-- 
2.24.1





^ permalink raw reply	[flat|nested] 162+ messages in thread

* [PATCH v29 01/12] Linux Random Number Generator
  2020-01-19 21:12         ` [PATCH v29 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
@ 2020-01-19 21:13           ` Stephan Müller
  2020-01-19 21:13           ` [PATCH v29 02/12] LRNG - allocate one DRNG instance per NUMA node Stephan Müller
                             ` (10 subsequent siblings)
  11 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2020-01-19 21:13 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap, Julia Lawall, Dan Carpenter

In an effort to provide a flexible implementation for a random number
generator that also delivers entropy during early boot time, allows
replacement of the deterministic random number generation mechanism,
implement the various components in separate code for easier
maintenance, and provide compliance to SP800-90[A|B|C], introduce
the Linux Random Number Generator (LRNG) framework.

The general design is as follows. Additional implementation details
are given in [1]. The LRNG consists of the following components:

1. The LRNG implements a DRNG. The DRNG always generates the
requested amount of output. When using the SP800-90A terminology
it operates without prediction resistance. The secondary DRNG
maintains a counter of how many bytes were generated since last
re-seed and a timer of the elapsed time since last re-seed. If either
the counter or the timer reaches a threshold, the secondary DRNG is
seeded from the entropy pool.

In case the Linux kernel detects a NUMA system, one secondary DRNG
instance per NUMA node is maintained.

2. The DRNG is seeded by concatenating the data from the
following sources:

(a) the output of the entropy pool,

(b) the Jitter RNG if available and enabled, and

(c) the CPU-based noise source such as Intel RDRAND if available and
enabled.

The entropy estimate of the data of all noise sources are added to
form the entropy estimate of the data used to seed the DRNG with.
The LRNG ensures, however, that the DRNG after seeding is at
maximum the security strength of the DRNG.

The LRNG is designed such that none of these noise sources can dominate
the other noise sources to provide seed data to the DRNG during due to
the following:

(a) During boot time, the amount of received interrupts are the trigger
points to (re)seed the DRNG.

(b) At runtime, the available entropy from the slow noise source is
concatenated with a pre-defined amount of data from the fast noise
sources. In addition, each DRNG reseed operation triggers external
noise source providers to deliver one block of data.

3. The entropy pool accumulates entropy obtained from certain events,
which will henceforth be collectively called "slow noise sources".
The entropy pool collects noise data from slow noise sources. Any data
received by the LRNG from the slow noise sources is inserted into the
entropy pool using an LFSR with a primitive and irreducible polynomial.
The following sources of entropy are used:

 (a) When an interrupt occurs, the high-resolution time stamp is mixed
into the LFSR. This time stamp is credited with heuristically implied
entropy.

 (b) HID event data like the key stroke or the mouse coordinates are
mixed into the LFSR. This data is not credited with entropy by the LRNG.

 (c) Device drivers may provide data that is mixed into the LFSR. This
data is not credited with entropy by the LRNG.

 (d) After the entropy pool is ``read'' by the DRNG, the data
used to seed the DRNG is mixed back into the entropy pool to
stir the pool. This data is not credited with entropy by the LRNG.

Any data provided from user space by either writing to /dev/random,
/dev/urandom or the IOCTL of RNDADDENTROPY on both device files
are always injected into the entropy pool.

In addition, when a hardware random number generator covered by the
Linux kernel HW generator framework wants to deliver random numbers,
it is injected into the entropy pool as well. HW generator noise source
is handled separately from the other noise source due to the fact that
the HW generator framework may decide by itself when to deliver data
whereas the other noise sources always requested for data driven by the
LRNG operation. Similarly any user space provided data is inserted into
the entropy pool.

When the DRNG requires data from the entropy pool, the entire
entropy pool is processed with an SP800-90A section 10.3.1 compliant
hash_df function to generate random numbers.

To speed up the interrupt handling code of the LRNG, the time stamp
collected for an interrupt event is truncated to the 8 least
significant bits. 64 truncated time stamps are concatenated and then
jointly inserted into the LFSR. During boot time, until the fully seeded
stage is reached, each time stamp with its 32 least significant bits is
inserted into the LFSR at the time of arrival.

The LRNG allows the DRNG mechanism to be changed at runtime. Per default,
a ChaCha20-based DRNG is used. The ChaCha20-DRNG implemented for the
LRNG is also provided as a stand-alone user space deterministic random
number generator. The LRNG also offers an SP800-90A DRBG based on the
Linux kernel crypto API DRBG implementation.

The processing of entropic data from the noise source before injecting
them into the DRNG is performed with the following mathematical
operations:

1. LFSR: The 8 least significant bits of the time stamp data received
from the interrupts are processed with an LFSR. That LFSR is implemented
identically to the LSFR used in the existing /dev/random implementation
except that it is capable of processing an entire word and that a
different polynomial is used. The reason for the different polynomial
is performance in a performance sensitive code section, the interrupt
handler. The chosen polynomials have 4 taps. Also, this LFSR-approach
is used in the OpenBSD /dev/random equivalent.

2. Concatenation: The temporary seed buffer used to seed the DRNG is
a concatenation of parts of the entropy pool data, and the CPU noise
source output.

The DRNG always tries to seed itself with 256 bits of entropy, except
during boot. In any case, if the noise sources cannot deliver that
amount, the available entropy is used and the DRNG keeps track on how
much entropy it was seeded with. The entropy implied by the LRNG
available in the entropy pool may be too conservative. To ensure
that during boot time all available entropy from the entropy pool is
transferred to the DRNG, the hash_df function always generates 256
data bits during boot to seed the DRNG. During boot, the DRNG is
seeded as follows:

1. The DRNG is reseeded from the entropy pool and potentially the fast
noise sources if the entropy pool has collected at least 32 bits of
entropy from the interrupt noise source. The goal of this step is to
ensure that the DRNG receives some initial entropy as early as
possible. In addition it receives the entropy available from
the fast noise sources.

2. The DRNG is reseeded from the entropy pool and potentially the fast
noise sources if all noise sources collectively can provide at least
128 bits of entropy.

3. The DRNG is reseeded from the entropy pool and potentially the fast
noise sources if all noise sources collectivel can provide at least 256
bits.

At the time of the reseeding steps, the DRNG requests as much entropy as
is available in order to skip certain steps and reach the seeding level
of 256 bits. This may imply that one or more of the aforementioned steps
are skipped.

In all listed steps, the DRNG is (re)seeded with a number of random
bytes from the entropy pool that is at most the amount of entropy
present in the entropy pool. This means that when the entropy pool
contains 128 or 256 bits of entropy, the DRNG is seeded with that
amount of entropy as well.

Before the DRNG is seeded with 256 bits of entropy in step 3,
requests of random data from /dev/random are not processed.

The hash_df operation providing random data from the entropy pool will
always require that all entropy sources collectively can deliver at
least 129 entropy bits as configured with (128 bits of entropy for
seeding plus one bit of entropy that is lost with the post
processing as defined in SP800-90B).

The DRNG operates as deterministic random number generator with the
following properties:

* The maximum number of random bytes that can be generated with one
DRNG generate operation is limited to 4096 bytes. When longer random
numbers are requested, multiple DRNG generate operations are performed.
The ChaCha20 DRNG as well as the SP800-90A DRBGs implement an update of
their state after completing a generate request for backtracking
resistance.

* The secondary DRNG is reseeded with whatever entropy is available –
in the worst case where no additional entropy can be provided by the
noise sources, the DRNG is not re-seeded and continues its operation
to try to reseed again after again the expiry of one of these thresholds:

 - If the last reseeding of the secondary DRNG is more than 600 seconds
   ago, or

 - 2^20 DRNG generate operations are performed, whatever comes first, or

 - the secondary DRNG is forced to reseed before the next generation of
   random numbers if data has been injected into the LRNG by writing data
   into /dev/random or /dev/urandom.

The chosen values prevent high-volume requests from user space to cause
frequent reseeding operations which drag down the performance of the
DRNG.

With the automatic reseeding after 600 seconds, the LRNG is triggered
to reseed itself before the first request after a suspend that put the
hardware to sleep for longer than 600 seconds.

The LRNG uses the following runtime memory using the currently
smallest configuration:

* 576 bytes (512 bytes for the entropy pool and 64 for the entropy pool
  meta data) for the entropy pool management

* 64 bytes per CPU for the time stamp array

To support smaller devices including IoT environments, this patch
allows reducing the runtime memory footprint of the LRNG at compile
time by selecting smaller entropy pool sizes.

The entropy pool has support for sizes of 256, 128 and 64 bytes supported
by primitive and irreducible polynomials.

The time stamp array is reduced to one atomic_t variable per CPU, i.e.
4 bytes when CONFIG_BASE_SMALL is selected during kernel
configuration. This implies that after the receipt of 4 interrupts on
one CPU, the data is injected into the LFSR. Depending on the behavior
of the CPU caches, this may imply that the average interrupt handler
execution time increases a bit, since instead of injecting 8 atomic_t
values at one given time into the LFSR, only one is processed which
may incur cache misses.

When selecting the compilation of a kernel for a small environment,
prevent the allocation of a buffer up to 4096 bytes to serve user space
requests. In this case, the stack variable of 64 bytes is used to serve
all user space requests.

The LRNG has the following properties:

* internal noise source: interrupts timing with fast boot time seeding

* 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().

* lockless LFSR to collect raw entropy supporing concurrency-free
  use of massive parallel systems

* use of standalone ChaCha20 based RNG with the option to use a
  different DRNG selectable at compile time

* "atomic" seeding of secondary DRBG to ensure full entropy transport

* instantiate one DRNG per NUMA node

* support for runtime switchable output DRNGs

* use of only well-defined entropy-preserving operations to collect,
compress and forward entropy: concatenation, LFSR, SP800-90A hash_df
function

* compile-time selectable entropy pool size: the choice also
uses the applicable LFSR polynomial to maintain the entropy pool
size

* support of small systems by allowing the reduction of the
runtime memory needs

Further details including the rationale for the design choices and
properties of the LRNG together with testing is provided at [1].
In addition, the documentation explains the conducted regression
tests to verify that the LRNG is API and ABI compatible with the
existing /dev/random implementation.

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

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Mathematical aspects Reviewed-by: "Peter, Matthias" <matthias.peter@bsi.bund.de>
Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 MAINTAINERS                         |   7 +
 drivers/char/Kconfig                |   2 +
 drivers/char/Makefile               |   9 +-
 drivers/char/lrng/Kconfig           |  67 +++
 drivers/char/lrng/Makefile          |   9 +
 drivers/char/lrng/lrng_archrandom.c |  93 ++++
 drivers/char/lrng/lrng_aux.c        | 148 +++++++
 drivers/char/lrng/lrng_chacha20.c   | 263 ++++++++++++
 drivers/char/lrng/lrng_chacha20.h   |  25 ++
 drivers/char/lrng/lrng_drng.c       | 400 +++++++++++++++++
 drivers/char/lrng/lrng_interfaces.c | 636 ++++++++++++++++++++++++++++
 drivers/char/lrng/lrng_internal.h   | 296 +++++++++++++
 drivers/char/lrng/lrng_lfsr.h       | 152 +++++++
 drivers/char/lrng/lrng_pool.c       | 586 +++++++++++++++++++++++++
 drivers/char/lrng/lrng_sw_noise.c   | 102 +++++
 drivers/char/lrng/lrng_sw_noise.h   |  57 +++
 include/linux/lrng.h                |  63 +++
 17 files changed, 2914 insertions(+), 1 deletion(-)
 create mode 100644 drivers/char/lrng/Kconfig
 create mode 100644 drivers/char/lrng/Makefile
 create mode 100644 drivers/char/lrng/lrng_archrandom.c
 create mode 100644 drivers/char/lrng/lrng_aux.c
 create mode 100644 drivers/char/lrng/lrng_chacha20.c
 create mode 100644 drivers/char/lrng/lrng_chacha20.h
 create mode 100644 drivers/char/lrng/lrng_drng.c
 create mode 100644 drivers/char/lrng/lrng_interfaces.c
 create mode 100644 drivers/char/lrng/lrng_internal.h
 create mode 100644 drivers/char/lrng/lrng_lfsr.h
 create mode 100644 drivers/char/lrng/lrng_pool.c
 create mode 100644 drivers/char/lrng/lrng_sw_noise.c
 create mode 100644 drivers/char/lrng/lrng_sw_noise.h
 create mode 100644 include/linux/lrng.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 4ae9768460f7..77f8298ba1be 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9606,6 +9606,13 @@ F:	Documentation/core-api/atomic_ops.rst
 F:	Documentation/core-api/refcount-vs-atomic.rst
 F:	Documentation/memory-barriers.txt
 
+LINUX RANDOM NUMBER GENERATOR (LRNG) DRIVER
+M:	Stephan Mueller <smueller@chronox.de>
+S:	Maintained
+W:	https://www.chronox.de/lrng.html
+F:	drivers/char/lrng/*
+F:	include/linux/lrng.h
+
 LIS3LV02D ACCELEROMETER DRIVER
 M:	Eric Piel <eric.piel@tremplin-utc.net>
 S:	Maintained
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 26956c006987..1e758735f633 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -535,6 +535,8 @@ config ADI
 	  and SSM (Silicon Secured Memory).  Intended consumers of this
 	  driver include crash and makedumpfile.
 
+source "drivers/char/lrng/Kconfig"
+
 endmenu
 
 config RANDOM_TRUST_CPU
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 7c5ea6f9df14..46ede09fd6d3 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -3,7 +3,14 @@
 # Makefile for the kernel character device drivers.
 #
 
-obj-y				+= mem.o random.o
+obj-y				+= mem.o
+
+ifeq ($(CONFIG_LRNG),y)
+  obj-y				+= lrng/
+else
+  obj-y				+= random.o
+endif
+
 obj-$(CONFIG_TTY_PRINTK)	+= ttyprintk.o
 obj-y				+= misc.o
 obj-$(CONFIG_ATARI_DSP56K)	+= dsp56k.o
diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
new file mode 100644
index 000000000000..56f13efd3592
--- /dev/null
+++ b/drivers/char/lrng/Kconfig
@@ -0,0 +1,67 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Linux Random Number Generator configuration
+#
+
+menuconfig LRNG
+	bool "Linux Random Number Generator"
+	help
+	  The Linux Random Number Generator (LRNG) is the replacement
+	  of the existing /dev/random provided with drivers/char/random.c.
+	  It generates entropy from different noise sources and
+	  delivers significant entropy during boot.
+
+if LRNG
+
+choice
+	prompt "LRNG Entropy Pool Size"
+	default LRNG_POOL_SIZE_4096
+	help
+	  Select the size of the LRNG entropy pool. The size of the
+	  entropy pool is relevant for the amount of entropy that
+	  the LRNG can maintain as a maximum. The larger the size
+	  of the entropy pool is the more entropy can be maintained
+	  but the less often older entropic values are overwritten
+	  with new entropy.
+
+	config LRNG_POOL_SIZE_512
+		bool "512 bits"
+
+	config LRNG_POOL_SIZE_1024
+		bool "1024 bits"
+
+	config LRNG_POOL_SIZE_2048
+		bool "2048 bits"
+
+	config LRNG_POOL_SIZE_4096
+		bool "4096 bits (default)"
+
+	config LRNG_POOL_SIZE_8192
+		bool "8192 bits"
+
+	config LRNG_POOL_SIZE_16384
+		bool "16384 bits"
+
+	config LRNG_POOL_SIZE_32768
+		bool "32768 bits"
+
+	config LRNG_POOL_SIZE_65536
+		bool "65536 bits"
+
+	config LRNG_POOL_SIZE_131072
+		bool "131072 bits"
+endchoice
+
+config LRNG_POOL_SIZE
+	int
+	default 0 if LRNG_POOL_SIZE_512
+	default 1 if LRNG_POOL_SIZE_1024
+	default 2 if LRNG_POOL_SIZE_2048
+	default 3 if LRNG_POOL_SIZE_4096
+	default 4 if LRNG_POOL_SIZE_8192
+	default 5 if LRNG_POOL_SIZE_16384
+	default 6 if LRNG_POOL_SIZE_32768
+	default 7 if LRNG_POOL_SIZE_65536
+	default 8 if LRNG_POOL_SIZE_131072
+
+endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
new file mode 100644
index 000000000000..1d2a0211973d
--- /dev/null
+++ b/drivers/char/lrng/Makefile
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for the Linux Random Number Generator.
+#
+
+obj-y				+= lrng_pool.o lrng_aux.o \
+				   lrng_sw_noise.o lrng_archrandom.o \
+				   lrng_drng.o lrng_chacha20.o \
+				   lrng_interfaces.o \
diff --git a/drivers/char/lrng/lrng_archrandom.c b/drivers/char/lrng/lrng_archrandom.c
new file mode 100644
index 000000000000..5e81c4e856d5
--- /dev/null
+++ b/drivers/char/lrng/lrng_archrandom.c
@@ -0,0 +1,93 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG Fast Noise Source: CPU-based noise source
+ *
+ * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/random.h>
+
+#include "lrng_internal.h"
+
+/*
+ * Estimated entropy of data is a 32th of LRNG_DRNG_SECURITY_STRENGTH_BITS.
+ * As we have no ability to review the implementation of those noise sources,
+ * it is prudent to have a conservative estimate here.
+ */
+#define LRNG_ARCHRANDOM_DEFAULT_STRENGTH (LRNG_DRNG_SECURITY_STRENGTH_BITS>>5)
+#define LRNG_ARCHRANDOM_TRUST_CPU_STRENGTH LRNG_DRNG_SECURITY_STRENGTH_BITS
+#ifdef CONFIG_RANDOM_TRUST_CPU
+static u32 archrandom = LRNG_ARCHRANDOM_TRUST_CPU_STRENGTH;
+#else
+static u32 archrandom = LRNG_ARCHRANDOM_DEFAULT_STRENGTH;
+#endif
+module_param(archrandom, uint, 0644);
+MODULE_PARM_DESC(archrandom, "Entropy in bits of 256 data bits from CPU noise source (e.g. RDRAND)");
+
+static int __init lrng_parse_trust_cpu(char *arg)
+{
+	int ret;
+	bool trust_cpu = false;
+
+	ret = kstrtobool(arg, &trust_cpu);
+	if (ret)
+		return ret;
+
+	if (trust_cpu)
+		archrandom = LRNG_ARCHRANDOM_TRUST_CPU_STRENGTH;
+	else
+		archrandom = LRNG_ARCHRANDOM_DEFAULT_STRENGTH;
+
+	return 0;
+}
+early_param("random.trust_cpu", lrng_parse_trust_cpu);
+
+/**
+ * lrng_get_arch() - Get CPU noise source entropy
+ *
+ * @outbuf: buffer to store entropy of size LRNG_DRNG_SECURITY_STRENGTH_BYTES
+ *
+ * Return:
+ * * > 0 on success where value provides the added entropy in bits
+ * *   0 if no fast source was available
+ */
+u32 lrng_get_arch(u8 *outbuf)
+{
+	u32 i, ent_bits = archrandom;
+
+	/* operate on full blocks */
+	BUILD_BUG_ON(LRNG_DRNG_SECURITY_STRENGTH_BYTES % sizeof(unsigned long));
+	/* ensure we have aligned buffers */
+	BUILD_BUG_ON(LRNG_KCAPI_ALIGN % sizeof(unsigned long));
+
+	if (!ent_bits)
+		return 0;
+
+	for (i = 0; i < LRNG_DRNG_SECURITY_STRENGTH_BYTES;
+	     i += sizeof(unsigned long)) {
+		if (!arch_get_random_seed_long((unsigned long *)(outbuf + i)) &&
+		    !arch_get_random_long((unsigned long *)(outbuf + i))) {
+			archrandom = 0;
+			return 0;
+		}
+	}
+
+	/* Obtain entropy statement -- cap entropy to buffer size in bits */
+	ent_bits = min_t(u32, ent_bits, LRNG_DRNG_SECURITY_STRENGTH_BITS);
+	pr_debug("obtained %u bits of entropy from CPU RNG noise source\n",
+		 ent_bits);
+	return ent_bits;
+}
+
+u32 lrng_slow_noise_req_entropy(u32 required_entropy_bits)
+{
+	u32 arch_ent_bits = min_t(u32, archrandom,
+				  LRNG_DRNG_SECURITY_STRENGTH_BITS);
+	u32 fast_noise_entropy = arch_ent_bits + lrng_jent_entropylevel();
+
+	if (fast_noise_entropy > required_entropy_bits)
+		return 0;
+	return (required_entropy_bits - fast_noise_entropy);
+}
diff --git a/drivers/char/lrng/lrng_aux.c b/drivers/char/lrng/lrng_aux.c
new file mode 100644
index 000000000000..b66c7795d067
--- /dev/null
+++ b/drivers/char/lrng/lrng_aux.c
@@ -0,0 +1,148 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG auxiliary interfaces
+ *
+ * Copyright (C) 2019 Stephan Mueller <smueller@chronox.de>
+ * Copyright (C) 2017 Jason A. Donenfeld <Jason@zx2c4.com>. All
+ * Rights Reserved.
+ * Copyright (C) 2016 Jason Cooper <jason@lakedaemon.net>
+ */
+
+#include <linux/mm.h>
+#include <linux/random.h>
+
+#include "lrng_internal.h"
+
+struct batched_entropy {
+	union {
+		u64 entropy_u64[LRNG_DRNG_BLOCKSIZE / sizeof(u64)];
+		u32 entropy_u32[LRNG_DRNG_BLOCKSIZE / sizeof(u32)];
+	};
+	unsigned int position;
+	spinlock_t batch_lock;
+};
+
+/*
+ * Get a random word for internal kernel use only. The quality of the random
+ * number is either as good as RDRAND or as good as /dev/urandom, with the
+ * goal of being quite fast and not depleting entropy.
+ */
+static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_u64) = {
+	.batch_lock	= __SPIN_LOCK_UNLOCKED(batched_entropy_u64.lock),
+};
+
+u64 get_random_u64(void)
+{
+	u64 ret;
+	unsigned long flags;
+	struct batched_entropy *batch;
+
+#if BITS_PER_LONG == 64
+	if (arch_get_random_long((unsigned long *)&ret))
+		return ret;
+#else
+	if (arch_get_random_long((unsigned long *)&ret) &&
+	    arch_get_random_long((unsigned long *)&ret + 1))
+		return ret;
+#endif
+
+	lrng_debug_report_seedlevel("get_random_u64");
+
+	batch = raw_cpu_ptr(&batched_entropy_u64);
+	spin_lock_irqsave(&batch->batch_lock, flags);
+	if (batch->position % ARRAY_SIZE(batch->entropy_u64) == 0) {
+		lrng_drng_get_atomic((u8 *)batch->entropy_u64,
+				      LRNG_DRNG_BLOCKSIZE);
+		batch->position = 0;
+	}
+	ret = batch->entropy_u64[batch->position++];
+	spin_unlock_irqrestore(&batch->batch_lock, flags);
+	return ret;
+}
+EXPORT_SYMBOL(get_random_u64);
+
+static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_u32) = {
+	.batch_lock	= __SPIN_LOCK_UNLOCKED(batched_entropy_u32.lock),
+};
+
+u32 get_random_u32(void)
+{
+	u32 ret;
+	unsigned long flags;
+	struct batched_entropy *batch;
+
+	if (arch_get_random_int(&ret))
+		return ret;
+
+	lrng_debug_report_seedlevel("get_random_u32");
+
+	batch = raw_cpu_ptr(&batched_entropy_u32);
+	spin_lock_irqsave(&batch->batch_lock, flags);
+	if (batch->position % ARRAY_SIZE(batch->entropy_u32) == 0) {
+		lrng_drng_get_atomic((u8 *)batch->entropy_u32,
+				      LRNG_DRNG_BLOCKSIZE);
+		batch->position = 0;
+	}
+	ret = batch->entropy_u32[batch->position++];
+	spin_unlock_irqrestore(&batch->batch_lock, flags);
+	return ret;
+}
+EXPORT_SYMBOL(get_random_u32);
+
+/*
+ * It's important to invalidate all potential batched entropy that might
+ * be stored before the crng is initialized, which we can do lazily by
+ * simply resetting the counter to zero so that it's re-extracted on the
+ * next usage.
+ */
+void invalidate_batched_entropy(void)
+{
+	int cpu;
+	unsigned long flags;
+
+	for_each_possible_cpu(cpu) {
+		struct batched_entropy *batched_entropy;
+
+		batched_entropy = per_cpu_ptr(&batched_entropy_u32, cpu);
+		spin_lock_irqsave(&batched_entropy->batch_lock, flags);
+		batched_entropy->position = 0;
+		spin_unlock(&batched_entropy->batch_lock);
+
+		batched_entropy = per_cpu_ptr(&batched_entropy_u64, cpu);
+		spin_lock(&batched_entropy->batch_lock);
+		batched_entropy->position = 0;
+		spin_unlock_irqrestore(&batched_entropy->batch_lock, flags);
+	}
+}
+
+/**
+ * randomize_page - Generate a random, page aligned address
+ * @start:	The smallest acceptable address the caller will take.
+ * @range:	The size of the area, starting at @start, within which the
+ *		random address must fall.
+ *
+ * If @start + @range would overflow, @range is capped.
+ *
+ * NOTE: Historical use of randomize_range, which this replaces, presumed that
+ * @start was already page aligned.  We now align it regardless.
+ *
+ * Return: A page aligned address within [start, start + range).  On error,
+ * @start is returned.
+ */
+unsigned long randomize_page(unsigned long start, unsigned long range)
+{
+	if (!PAGE_ALIGNED(start)) {
+		range -= PAGE_ALIGN(start) - start;
+		start = PAGE_ALIGN(start);
+	}
+
+	if (start > ULONG_MAX - range)
+		range = ULONG_MAX - start;
+
+	range >>= PAGE_SHIFT;
+
+	if (range == 0)
+		return start;
+
+	return start + (get_random_long() % range << PAGE_SHIFT);
+}
diff --git a/drivers/char/lrng/lrng_chacha20.c b/drivers/char/lrng/lrng_chacha20.c
new file mode 100644
index 000000000000..9240dc9ce26d
--- /dev/null
+++ b/drivers/char/lrng/lrng_chacha20.c
@@ -0,0 +1,263 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * Backend for the LRNG providing the cryptographic primitives using
+ * ChaCha20 cipher implementations.
+ *
+ * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <crypto/chacha.h>
+#include <linux/cryptohash.h>
+#include <linux/lrng.h>
+#include <linux/random.h>
+#include <linux/slab.h>
+
+#include "lrng_chacha20.h"
+#include "lrng_internal.h"
+
+/******************************* ChaCha20 DRNG *******************************/
+
+#define CHACHA_BLOCK_WORDS	(CHACHA_BLOCK_SIZE / sizeof(u32))
+
+struct chacha20_state {
+	struct chacha20_block block;
+};
+
+/*
+ * Have a static memory blocks for the ChaCha20 DRNG instance to avoid calling
+ * kmalloc too early in the boot cycle. For subsequent allocation requests,
+ * such as per-NUMA-node DRNG instances, kmalloc will be used.
+ */
+struct chacha20_state chacha20;
+
+/**
+ * Update of the ChaCha20 state by either using an unused buffer part or by
+ * generating one ChaCha20 block which is half of the state of the ChaCha20.
+ * The block is XORed into the key part of the state. This shall ensure
+ * backtracking resistance as well as a proper mix of the ChaCha20 state once
+ * the key is injected.
+ */
+static void lrng_chacha20_update(struct chacha20_state *chacha20_state,
+				 u32 *buf, u32 used_words)
+{
+	struct chacha20_block *chacha20 = &chacha20_state->block;
+	u32 i, tmp[CHACHA_BLOCK_WORDS];
+
+	BUILD_BUG_ON(sizeof(struct chacha20_block) != CHACHA_BLOCK_SIZE);
+	BUILD_BUG_ON(CHACHA_BLOCK_SIZE != 2 * CHACHA_KEY_SIZE);
+
+	if (used_words > CHACHA_KEY_SIZE_WORDS) {
+		chacha20_block(&chacha20->constants[0], (u8 *)tmp);
+		for (i = 0; i < CHACHA_KEY_SIZE_WORDS; i++)
+			chacha20->key.u[i] ^= tmp[i];
+		memzero_explicit(tmp, sizeof(tmp));
+	} else {
+		for (i = 0; i < CHACHA_KEY_SIZE_WORDS; i++)
+			chacha20->key.u[i] ^= buf[i + used_words];
+	}
+
+	/* Deterministic increment of nonce as required in RFC 7539 chapter 4 */
+	chacha20->nonce[0]++;
+	if (chacha20->nonce[0] == 0)
+		chacha20->nonce[1]++;
+	if (chacha20->nonce[1] == 0)
+		chacha20->nonce[2]++;
+
+	/* Leave counter untouched as it is start value is undefined in RFC */
+}
+
+/*
+ * Seed the ChaCha20 DRNG by injecting the input data into the key part of
+ * the ChaCha20 state. If the input data is longer than the ChaCha20 key size,
+ * perform a ChaCha20 operation after processing of key size input data.
+ * This operation shall spread out the entropy into the ChaCha20 state before
+ * new entropy is injected into the key part.
+ */
+static int lrng_cc20_drng_seed_helper(void *drng, const u8 *inbuf, u32 inbuflen)
+{
+	struct chacha20_state *chacha20_state = (struct chacha20_state *)drng;
+	struct chacha20_block *chacha20 = &chacha20_state->block;
+
+	while (inbuflen) {
+		u32 i, todo = min_t(u32, inbuflen, CHACHA_KEY_SIZE);
+
+		for (i = 0; i < todo; i++)
+			chacha20->key.b[i] ^= inbuf[i];
+
+		/* Break potential dependencies between the inbuf key blocks */
+		lrng_chacha20_update(chacha20_state, NULL,
+				     CHACHA_BLOCK_WORDS);
+		inbuf += todo;
+		inbuflen -= todo;
+	}
+
+	return 0;
+}
+
+/*
+ * Chacha20 DRNG generation of random numbers: the stream output of ChaCha20
+ * is the random number. After the completion of the generation of the
+ * stream, the entire ChaCha20 state is updated.
+ *
+ * Note, as the ChaCha20 implements a 32 bit counter, we must ensure
+ * that this function is only invoked for at most 2^32 - 1 ChaCha20 blocks
+ * before a reseed or an update happens. This is ensured by the variable
+ * outbuflen which is a 32 bit integer defining the number of bytes to be
+ * generated by the ChaCha20 DRNG. At the end of this function, an update
+ * operation is invoked which implies that the 32 bit counter will never be
+ * overflown in this implementation.
+ */
+static int lrng_cc20_drng_generate_helper(void *drng, u8 *outbuf, u32 outbuflen)
+{
+	struct chacha20_state *chacha20_state = (struct chacha20_state *)drng;
+	struct chacha20_block *chacha20 = &chacha20_state->block;
+	u32 aligned_buf[CHACHA_BLOCK_WORDS], ret = outbuflen,
+	    used = CHACHA_BLOCK_WORDS;
+	int zeroize_buf = 0;
+
+	while (outbuflen >= CHACHA_BLOCK_SIZE) {
+		chacha20_block(&chacha20->constants[0], outbuf);
+		outbuf += CHACHA_BLOCK_SIZE;
+		outbuflen -= CHACHA_BLOCK_SIZE;
+	}
+
+	if (outbuflen) {
+		chacha20_block(&chacha20->constants[0], (u8 *)aligned_buf);
+		memcpy(outbuf, aligned_buf, outbuflen);
+		used = ((outbuflen + sizeof(aligned_buf[0]) - 1) /
+			sizeof(aligned_buf[0]));
+		zeroize_buf = 1;
+	}
+
+	lrng_chacha20_update(chacha20_state, aligned_buf, used);
+
+	if (zeroize_buf)
+		memzero_explicit(aligned_buf, sizeof(aligned_buf));
+
+	return ret;
+}
+
+void lrng_cc20_init_state(struct chacha20_state *state)
+{
+	struct chacha20_block *chacha20 = &state->block;
+	unsigned long v;
+	u32 i;
+
+	lrng_cc20_init_rfc7539(chacha20);
+
+	for (i = 0; i < CHACHA_KEY_SIZE_WORDS; i++) {
+		chacha20->key.u[i] ^= jiffies;
+		chacha20->key.u[i] ^= random_get_entropy();
+		if (arch_get_random_seed_long(&v) || arch_get_random_long(&v))
+			chacha20->key.u[i] ^= v;
+	}
+
+	for (i = 0; i < 3; i++) {
+		chacha20->nonce[i] ^= jiffies;
+		chacha20->nonce[i] ^= random_get_entropy();
+		if (arch_get_random_seed_long(&v) || arch_get_random_long(&v))
+			chacha20->nonce[i] ^= v;
+	}
+
+	pr_info("ChaCha20 core initialized\n");
+}
+
+/*
+ * Allocation of the DRNG state
+ */
+static void *lrng_cc20_drng_alloc(u32 sec_strength)
+{
+	struct chacha20_state *state = NULL;
+
+	if (sec_strength > CHACHA_KEY_SIZE) {
+		pr_err("Security strength of ChaCha20 DRNG (%u bits) lower than requested by LRNG (%u bits)\n",
+			CHACHA_KEY_SIZE * 8, sec_strength * 8);
+		return ERR_PTR(-EINVAL);
+	}
+	if (sec_strength < CHACHA_KEY_SIZE)
+		pr_warn("Security strength of ChaCha20 DRNG (%u bits) higher than requested by LRNG (%u bits)\n",
+			CHACHA_KEY_SIZE * 8, sec_strength * 8);
+
+	state = kmalloc(sizeof(struct chacha20_state), GFP_KERNEL);
+	if (!state)
+		return ERR_PTR(-ENOMEM);
+	pr_debug("memory for ChaCha20 core allocated\n");
+
+	lrng_cc20_init_state(state);
+
+	return state;
+}
+
+static void lrng_cc20_drng_dealloc(void *drng)
+{
+	struct chacha20_state *chacha20_state = (struct chacha20_state *)drng;
+
+	if (drng == &chacha20) {
+		memzero_explicit(chacha20_state, sizeof(*chacha20_state));
+		pr_debug("static ChaCha20 core zeroized\n");
+		return;
+	}
+
+	pr_debug("ChaCha20 core zeroized and freed\n");
+	kzfree(chacha20_state);
+}
+
+/******************************* Hash Operation *******************************/
+
+static void *lrng_cc20_hash_alloc(const u8 *key, u32 keylen)
+{
+	pr_info("Hash SHA-1 allocated\n");
+	return NULL;
+}
+
+static void lrng_cc20_hash_dealloc(void *hash)
+{
+}
+
+static u32 lrng_cc20_hash_digestsize(void *hash)
+{
+	return (SHA_DIGEST_WORDS * sizeof(u32));
+}
+
+static int lrng_cc20_hash_buffer(void *hash, const u8 *inbuf, u32 inbuflen,
+				 u8 *digest)
+{
+	u32 i;
+	u32 workspace[SHA_WORKSPACE_WORDS];
+
+	WARN_ON(inbuflen % (SHA_WORKSPACE_WORDS * sizeof(u32)));
+
+	sha_init((u32 *)digest);
+	for (i = 0; i < inbuflen; i += (SHA_WORKSPACE_WORDS * sizeof(u32)))
+		sha_transform((u32 *)digest, (inbuf + i), workspace);
+	memzero_explicit(workspace, sizeof(workspace));
+
+	return 0;
+}
+
+static const char *lrng_cc20_drng_name(void)
+{
+	const char *cc20_drng_name = "ChaCha20 DRNG";
+	return cc20_drng_name;
+}
+
+static const char *lrng_cc20_hash_name(void)
+{
+	const char *cc20_hash_name = "SHA-1";
+	return cc20_hash_name;
+}
+
+const struct lrng_crypto_cb lrng_cc20_crypto_cb = {
+	.lrng_drng_name			= lrng_cc20_drng_name,
+	.lrng_hash_name			= lrng_cc20_hash_name,
+	.lrng_drng_alloc		= lrng_cc20_drng_alloc,
+	.lrng_drng_dealloc		= lrng_cc20_drng_dealloc,
+	.lrng_drng_seed_helper		= lrng_cc20_drng_seed_helper,
+	.lrng_drng_generate_helper	= lrng_cc20_drng_generate_helper,
+	.lrng_hash_alloc		= lrng_cc20_hash_alloc,
+	.lrng_hash_dealloc		= lrng_cc20_hash_dealloc,
+	.lrng_hash_digestsize		= lrng_cc20_hash_digestsize,
+	.lrng_hash_buffer		= lrng_cc20_hash_buffer,
+};
diff --git a/drivers/char/lrng/lrng_chacha20.h b/drivers/char/lrng/lrng_chacha20.h
new file mode 100644
index 000000000000..0387ad59cfbc
--- /dev/null
+++ b/drivers/char/lrng/lrng_chacha20.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
+/*
+ * LRNG ChaCha20 definitions
+ *
+ * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#include <crypto/chacha.h>
+
+/* State according to RFC 7539 section 2.3 */
+struct chacha20_block {
+	u32 constants[4];
+	union {
+#define CHACHA_KEY_SIZE_WORDS (CHACHA_KEY_SIZE / sizeof(u32))
+		u32 u[CHACHA_KEY_SIZE_WORDS];
+		u8  b[CHACHA_KEY_SIZE];
+	} key;
+	u32 counter;
+	u32 nonce[3];
+};
+
+static inline void lrng_cc20_init_rfc7539(struct chacha20_block *chacha20)
+{
+	memcpy(&chacha20->constants[0], "expand 32-byte k", 16);
+}
diff --git a/drivers/char/lrng/lrng_drng.c b/drivers/char/lrng/lrng_drng.c
new file mode 100644
index 000000000000..c11f010f2fa8
--- /dev/null
+++ b/drivers/char/lrng/lrng_drng.c
@@ -0,0 +1,400 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG DRNG processing
+ *
+ * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/lrng.h>
+
+#include "lrng_internal.h"
+
+/*
+ * Maximum number of seconds between DRNG reseed intervals of the DRNG. Note,
+ * this is enforced with the next request of random numbers from the
+ * DRNG. Setting this value to zero implies a reseeding attempt before every
+ * generated random number.
+ */
+int lrng_drng_reseed_max_time = 600;
+
+static atomic_t lrng_avail = ATOMIC_INIT(0);
+
+DEFINE_MUTEX(lrng_crypto_cb_update);
+
+/* DRNG for /dev/urandom, getrandom(2), get_random_bytes */
+static struct lrng_drng lrng_drng_init = {
+	.drng		= &chacha20,
+	.crypto_cb	= &lrng_cc20_crypto_cb,
+	.lock		= __MUTEX_INITIALIZER(lrng_drng_init.lock),
+	.spin_lock	= __SPIN_LOCK_UNLOCKED(lrng_drng_init.spin_lock)
+};
+
+/*
+ * DRNG for get_random_bytes when called in atomic context. This
+ * DRNG will always use the ChaCha20 DRNG. It will never benefit from a
+ * DRNG switch like the "regular" DRNG. If there was no DRNG switch, the atomic
+ * DRNG is identical to the "regular" DRNG.
+ *
+ * The reason for having this is due to the fact that DRNGs other than
+ * the ChaCha20 DRNG may sleep.
+ */
+static struct lrng_drng lrng_drng_atomic = {
+	.drng		= &chacha20,
+	.crypto_cb	= &lrng_cc20_crypto_cb,
+	.spin_lock	= __SPIN_LOCK_UNLOCKED(lrng_drng_atomic.spin_lock)
+};
+
+/********************************** Helper ************************************/
+
+bool lrng_get_available(void)
+{
+	return likely(atomic_read(&lrng_avail));
+}
+
+void lrng_set_available(void)
+{
+	atomic_set(&lrng_avail, 1);
+}
+
+struct lrng_drng *lrng_drng_init_instance(void)
+{
+	return &lrng_drng_init;
+}
+
+struct lrng_drng *lrng_drng_atomic_instance(void)
+{
+	return &lrng_drng_atomic;
+}
+
+void lrng_drng_reset(struct lrng_drng *drng)
+{
+	atomic_set(&drng->requests, LRNG_DRNG_RESEED_THRESH);
+	drng->last_seeded = jiffies;
+	drng->fully_seeded = false;
+	drng->force_reseed = true;
+	pr_debug("reset DRNG\n");
+}
+
+/************************* Random Number Generation ***************************/
+
+/* Inject a data buffer into the DRNG */
+static void lrng_drng_inject(struct lrng_drng *drng,
+			     const u8 *inbuf, u32 inbuflen)
+{
+	const char *drng_type = unlikely(drng == &lrng_drng_atomic) ?
+				"atomic" : "regular";
+	unsigned long flags = 0;
+
+	BUILD_BUG_ON(LRNG_DRNG_RESEED_THRESH > INT_MAX);
+	pr_debug("seeding %s DRNG with %u bytes\n", drng_type, inbuflen);
+	lrng_drng_lock(drng, &flags);
+	if (drng->crypto_cb->lrng_drng_seed_helper(drng->drng,
+						    inbuf, inbuflen) < 0) {
+		pr_warn("seeding of %s DRNG failed\n", drng_type);
+		atomic_set(&drng->requests, 1);
+	} else {
+		pr_debug("%s DRNG stats since last seeding: %lu secs; generate calls: %d\n",
+			 drng_type,
+			 (time_after(jiffies, drng->last_seeded) ?
+			  (jiffies - drng->last_seeded) : 0) / HZ,
+			 (LRNG_DRNG_RESEED_THRESH -
+			  atomic_read(&drng->requests)));
+		drng->last_seeded = jiffies;
+		atomic_set(&drng->requests, LRNG_DRNG_RESEED_THRESH);
+		drng->force_reseed = false;
+
+		if (drng->drng == lrng_drng_atomic.drng) {
+			lrng_drng_atomic.last_seeded = jiffies;
+			atomic_set(&lrng_drng_atomic.requests,
+				   LRNG_DRNG_RESEED_THRESH);
+			lrng_drng_atomic.force_reseed = false;
+		}
+	}
+	lrng_drng_unlock(drng, &flags);
+}
+
+/*
+ * Perform the seeding of the DRNG with data from noise source
+ */
+static inline int _lrng_drng_seed(struct lrng_drng *drng)
+{
+	struct entropy_buf seedbuf __aligned(LRNG_KCAPI_ALIGN);
+	unsigned long flags = 0;
+	u32 total_entropy_bits;
+	int ret;
+
+	lrng_drng_lock(drng, &flags);
+	total_entropy_bits = lrng_fill_seed_buffer(drng->crypto_cb, drng->hash,
+						   &seedbuf, 0);
+	lrng_drng_unlock(drng, &flags);
+
+	/* Allow the seeding operation to be called again */
+	lrng_pool_unlock();
+	lrng_init_ops(total_entropy_bits);
+	ret = total_entropy_bits >> 3;
+
+	lrng_drng_inject(drng, (u8 *)&seedbuf, sizeof(seedbuf));
+	memzero_explicit(&seedbuf, sizeof(seedbuf));
+
+	return ret;
+}
+
+static int lrng_drng_get(struct lrng_drng *drng, u8 *outbuf, u32 outbuflen);
+static void lrng_drng_seed(struct lrng_drng *drng)
+{
+	int ret = _lrng_drng_seed(drng);
+
+	if (ret >= LRNG_DRNG_SECURITY_STRENGTH_BYTES)
+		drng->fully_seeded = true;
+
+	BUILD_BUG_ON(LRNG_MIN_SEED_ENTROPY_BITS >
+		     LRNG_DRNG_SECURITY_STRENGTH_BITS);
+
+	/*
+	 * Reseed atomic DRNG from current DRNG,
+	 *
+	 * We can obtain random numbers from DRNG as the lock type
+	 * chosen by lrng_drng_get is usable with the current caller.
+	 */
+	if ((drng->drng != lrng_drng_atomic.drng) &&
+	    (lrng_drng_atomic.force_reseed ||
+	     atomic_read(&lrng_drng_atomic.requests) <= 0 ||
+	     time_after(jiffies, lrng_drng_atomic.last_seeded +
+			lrng_drng_reseed_max_time * HZ))) {
+		u8 seedbuf[LRNG_DRNG_SECURITY_STRENGTH_BYTES]
+						__aligned(LRNG_KCAPI_ALIGN);
+
+		ret = lrng_drng_get(drng, seedbuf, sizeof(seedbuf));
+
+		if (ret < 0) {
+			pr_warn("Error generating random numbers for atomic DRNG: %d\n",
+				ret);
+		} else {
+			lrng_drng_inject(&lrng_drng_atomic, seedbuf, ret);
+		}
+		memzero_explicit(&seedbuf, sizeof(seedbuf));
+	}
+}
+
+static inline void _lrng_drng_seed_work(struct lrng_drng *drng, u32 node)
+{
+	pr_debug("reseed triggered by interrupt noise source for DRNG on NUMA node %d\n",
+		 node);
+	lrng_drng_seed(drng);
+	if (drng->fully_seeded) {
+		/* Prevent reseed storm */
+		drng->last_seeded += node * 100 * HZ;
+		/* Prevent draining of pool on idle systems */
+		lrng_drng_reseed_max_time += 100;
+	}
+}
+
+/*
+ * DRNG reseed trigger: Kernel thread handler triggered by the schedule_work()
+ */
+void lrng_drng_seed_work(struct work_struct *dummy)
+{
+	struct lrng_drng **lrng_drng = lrng_drng_instances();
+	u32 node;
+
+	if (lrng_drng) {
+		for_each_online_node(node) {
+			struct lrng_drng *drng = lrng_drng[node];
+
+			if (drng && !drng->fully_seeded) {
+				_lrng_drng_seed_work(drng, node);
+				goto out;
+			}
+		}
+		lrng_pool_all_numa_nodes_seeded();
+	} else {
+		if (!lrng_drng_init.fully_seeded)
+			_lrng_drng_seed_work(&lrng_drng_init, 0);
+	}
+
+out:
+	/* Allow the seeding operation to be called again */
+	lrng_pool_unlock();
+}
+
+/* Force all DRNGs to reseed before next generation */
+void lrng_drng_force_reseed(void)
+{
+	struct lrng_drng **lrng_drng = lrng_drng_instances();
+	u32 node;
+
+	if (!lrng_drng) {
+		lrng_drng_init.force_reseed = true;
+		pr_debug("force reseed of initial DRNG\n");
+		return;
+	}
+	for_each_online_node(node) {
+		struct lrng_drng *drng = lrng_drng[node];
+
+		if (!drng)
+			continue;
+
+		drng->force_reseed = true;
+		pr_debug("force reseed of DRNG on node %u\n", node);
+	}
+	lrng_drng_atomic.force_reseed = true;
+}
+
+/**
+ * lrng_drng_get() - Get random data out of the DRNG which is reseeded
+ * frequently.
+ *
+ * @outbuf: buffer for storing random data
+ * @outbuflen: length of outbuf
+ *
+ * Return:
+ * * < 0 in error case (DRNG generation or update failed)
+ * * >=0 returning the returned number of bytes
+ */
+static int lrng_drng_get(struct lrng_drng *drng, u8 *outbuf, u32 outbuflen)
+{
+	unsigned long flags = 0;
+	u32 processed = 0;
+
+	if (!outbuf || !outbuflen)
+		return 0;
+
+	outbuflen = min_t(size_t, outbuflen, INT_MAX);
+
+	lrng_drngs_init_cc20();
+
+	while (outbuflen) {
+		u32 todo = min_t(u32, outbuflen, LRNG_DRNG_MAX_REQSIZE);
+		int ret;
+
+		/* All but the atomic DRNG are seeded during generation */
+		if (atomic_dec_and_test(&drng->requests) ||
+		    drng->force_reseed ||
+		    time_after(jiffies, drng->last_seeded +
+			       lrng_drng_reseed_max_time * HZ)) {
+			if (likely(drng != &lrng_drng_atomic)) {
+				if (lrng_pool_trylock())
+					atomic_set(&drng->requests, 1);
+				else
+					lrng_drng_seed(drng);
+			}
+		}
+
+		lrng_drng_lock(drng, &flags);
+		ret = drng->crypto_cb->lrng_drng_generate_helper(
+					drng->drng, outbuf + processed, todo);
+		lrng_drng_unlock(drng, &flags);
+		if (ret <= 0) {
+			pr_warn("getting random data from DRNG failed (%d)\n",
+				ret);
+			return -EFAULT;
+		}
+		processed += ret;
+		outbuflen -= ret;
+	}
+
+	return processed;
+}
+
+int lrng_drng_get_atomic(u8 *outbuf, u32 outbuflen)
+{
+	return lrng_drng_get(&lrng_drng_atomic, outbuf, outbuflen);
+}
+
+int lrng_drng_get_sleep(u8 *outbuf, u32 outbuflen)
+{
+	struct lrng_drng **lrng_drng = lrng_drng_instances();
+	struct lrng_drng *drng = &lrng_drng_init;
+	int node = numa_node_id();
+
+	might_sleep();
+
+	if (lrng_drng && lrng_drng[node] && lrng_drng[node]->fully_seeded)
+		drng = lrng_drng[node];
+
+	return lrng_drng_get(drng, outbuf, outbuflen);
+}
+
+/* Initialize the default DRNG during boot */
+void lrng_drngs_init_cc20(void)
+{
+	unsigned long flags = 0;
+
+	if (lrng_get_available())
+		return;
+
+	lrng_drng_lock(&lrng_drng_init, &flags);
+	if (lrng_get_available()) {
+		lrng_drng_unlock(&lrng_drng_init, &flags);
+		return;
+	}
+
+	lrng_drng_reset(&lrng_drng_init);
+	lrng_cc20_init_state(&chacha20);
+	lrng_state_init_seed_work();
+	lrng_drng_unlock(&lrng_drng_init, &flags);
+
+	lrng_drng_lock(&lrng_drng_atomic, &flags);
+	lrng_drng_reset(&lrng_drng_atomic);
+	/*
+	 * We do not initialize the state of the atomic DRNG as it is identical
+	 * to the DRNG at this point.
+	 */
+	lrng_drng_unlock(&lrng_drng_atomic, &flags);
+
+	lrng_set_available();
+}
+
+/* Reset LRNG such that all existing entropy is gone */
+static void _lrng_reset(struct work_struct *work)
+{
+	struct lrng_drng **lrng_drng = lrng_drng_instances();
+	unsigned long flags = 0;
+
+	if (!lrng_drng) {
+		lrng_drng_lock(&lrng_drng_init, &flags);
+		lrng_drng_reset(&lrng_drng_init);
+		lrng_drng_unlock(&lrng_drng_init, &flags);
+	} else {
+		u32 node;
+
+		for_each_online_node(node) {
+			struct lrng_drng *drng = lrng_drng[node];
+
+			if (!drng)
+				continue;
+			lrng_drng_lock(drng, &flags);
+			lrng_drng_reset(drng);
+			lrng_drng_unlock(drng, &flags);
+		}
+	}
+	lrng_set_entropy_thresh(LRNG_INIT_ENTROPY_BITS +
+				LRNG_CONDITIONING_ENTROPY_LOSS);
+
+	lrng_reset_state();
+}
+
+static DECLARE_WORK(lrng_reset_work, _lrng_reset);
+
+void lrng_reset(void)
+{
+	schedule_work(&lrng_reset_work);
+}
+
+/***************************** Initialize LRNG *******************************/
+
+static int __init lrng_init(void)
+{
+	lrng_drngs_init_cc20();
+
+	lrng_drngs_numa_alloc();
+	return 0;
+}
+
+late_initcall(lrng_init);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
+MODULE_DESCRIPTION("Linux Random Number Generator");
diff --git a/drivers/char/lrng/lrng_interfaces.c b/drivers/char/lrng/lrng_interfaces.c
new file mode 100644
index 000000000000..6ad860866354
--- /dev/null
+++ b/drivers/char/lrng/lrng_interfaces.c
@@ -0,0 +1,636 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG User and kernel space interfaces
+ *
+ * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/freezer.h>
+#include <linux/fs.h>
+#include <linux/genhd.h>
+#include <linux/kthread.h>
+#include <linux/poll.h>
+#include <linux/preempt.h>
+#include <linux/random.h>
+#include <linux/slab.h>
+#include <linux/syscalls.h>
+#include <linux/timex.h>
+
+#include "lrng_internal.h"
+
+/*
+ * If the entropy count falls under this number of bits, then we
+ * should wake up processes which are selecting or polling on write
+ * access to /dev/random.
+ */
+u32 lrng_write_wakeup_bits = LRNG_WRITE_WAKEUP_ENTROPY;
+
+static LIST_HEAD(lrng_ready_list);
+static DEFINE_SPINLOCK(lrng_ready_list_lock);
+
+static DECLARE_WAIT_QUEUE_HEAD(lrng_write_wait);
+static DECLARE_WAIT_QUEUE_HEAD(lrng_init_wait);
+static struct fasync_struct *fasync;
+
+struct ctl_table random_table[];
+/********************************** Helper ***********************************/
+
+/* Is the DRNG seed level too low? */
+static inline bool lrng_need_entropy(void)
+{
+	return (lrng_avail_entropy() < lrng_write_wakeup_bits);
+}
+
+void lrng_writer_wakeup(void)
+{
+	if (lrng_need_entropy() && wq_has_sleeper(&lrng_write_wait)) {
+		wake_up_interruptible(&lrng_write_wait);
+		kill_fasync(&fasync, SIGIO, POLL_OUT);
+	}
+}
+
+void lrng_init_wakeup(void)
+{
+	wake_up_all(&lrng_init_wait);
+	kill_fasync(&fasync, SIGIO, POLL_IN);
+}
+
+/**
+ * lrng_process_ready_list() - Ping all kernel internal callers waiting until
+ * the DRNG is at least minimally seeded to inform that the DRNG reached that
+ * seed level.
+ *
+ * When the SP800-90B testing is enabled, the ping only happens if the SP800-90B
+ * startup health tests are completed. This implies that kernel internal
+ * callers always have an SP800-90B compliant noise source when being
+ * pinged.
+ */
+void lrng_process_ready_list(void)
+{
+	unsigned long flags;
+	struct random_ready_callback *rdy, *tmp;
+
+	if (!lrng_sp80090b_startup_complete())
+		return;
+
+	spin_lock_irqsave(&lrng_ready_list_lock, flags);
+	list_for_each_entry_safe(rdy, tmp, &lrng_ready_list, list) {
+		struct module *owner = rdy->owner;
+
+		list_del_init(&rdy->list);
+		rdy->func(rdy);
+		module_put(owner);
+	}
+	spin_unlock_irqrestore(&lrng_ready_list_lock, flags);
+}
+
+void lrng_debug_report_seedlevel(const char *name)
+{
+#ifdef CONFIG_WARN_ALL_UNSEEDED_RANDOM
+	static void *previous = NULL;
+	void *caller = (void *) _RET_IP_;
+
+	if (READ_ONCE(previous) == caller)
+		return;
+
+	if (!lrng_state_min_seeded())
+		pr_notice("%pS %s called without reaching mimimally seeded level (available entropy %u)\n",
+			  caller, name, lrng_avail_entropy());
+
+	WRITE_ONCE(previous, caller);
+#endif
+}
+
+/************************ LRNG kernel input interfaces ************************/
+
+/**
+ * add_hwgenerator_randomness() - Interface for in-kernel drivers of true
+ * hardware RNGs.
+ *
+ * Those devices may produce endless random bits and will be throttled
+ * when our pool is full.
+ *
+ * @buffer: buffer holding the entropic data from HW noise sources to be used to
+ *	    insert into entropy pool.
+ * @count: length of buffer
+ * @entropy_bits: amount of entropy in buffer (value is in bits)
+ */
+void add_hwgenerator_randomness(const char *buffer, size_t count,
+				size_t entropy_bits)
+{
+	/*
+	 * Suspend writing if we are fully loaded with entropy.
+	 * We'll be woken up again once below lrng_write_wakeup_thresh,
+	 * or when the calling thread is about to terminate.
+	 */
+	wait_event_interruptible(lrng_write_wait,
+				lrng_need_entropy() ||
+				lrng_state_exseed_allow(lrng_noise_source_hw) ||
+				kthread_should_stop());
+	lrng_state_exseed_set(lrng_noise_source_hw, false);
+	lrng_pool_lfsr_nonaligned(buffer, count);
+	lrng_pool_add_entropy(entropy_bits);
+}
+EXPORT_SYMBOL_GPL(add_hwgenerator_randomness);
+
+/**
+ * add_bootloader_randomness() - Handle random seed passed by bootloader.
+ *
+ * If the seed is trustworthy, it would be regarded as hardware RNGs. Otherwise
+ * it would be regarded as device data.
+ * The decision is controlled by CONFIG_RANDOM_TRUST_BOOTLOADER.
+ *
+ * @buf: buffer holding the entropic data from HW noise sources to be used to
+ *	 insert into entropy pool.
+ * @size: length of buffer
+ */
+void add_bootloader_randomness(const void *buf, unsigned int size)
+{
+	if (IS_ENABLED(CONFIG_RANDOM_TRUST_BOOTLOADER))
+		add_hwgenerator_randomness(buf, size, size * 8);
+	else
+		add_device_randomness(buf, size);
+}
+EXPORT_SYMBOL_GPL(add_bootloader_randomness);
+
+/*
+ * Callback for HID layer -- use the HID event values to stir the entropy pool
+ */
+void add_input_randomness(unsigned int type, unsigned int code,
+			  unsigned int value)
+{
+	static unsigned char last_value;
+
+	/* ignore autorepeat and the like */
+	if (value == last_value)
+		return;
+
+	last_value = value;
+
+	lrng_pool_lfsr_u32((type << 4) ^ code ^ (code >> 4) ^ value);
+}
+EXPORT_SYMBOL_GPL(add_input_randomness);
+
+/**
+ * add_device_randomness() - Add device- or boot-specific data to the entropy
+ * pool to help initialize it.
+ *
+ * None of this adds any entropy; it is meant to avoid the problem of
+ * the entropy pool having similar initial state across largely
+ * identical devices.
+ *
+ * @buf: buffer holding the entropic data from HW noise sources to be used to
+ *	 insert into entropy pool.
+ * @size: length of buffer
+ */
+void add_device_randomness(const void *buf, unsigned int size)
+{
+	lrng_pool_lfsr_nonaligned((u8 *)buf, size);
+	lrng_pool_lfsr_u32(random_get_entropy());
+	lrng_pool_lfsr_u32(jiffies);
+}
+EXPORT_SYMBOL(add_device_randomness);
+
+#ifdef CONFIG_BLOCK
+void rand_initialize_disk(struct gendisk *disk) { }
+void add_disk_randomness(struct gendisk *disk) { }
+EXPORT_SYMBOL(add_disk_randomness);
+#endif
+
+/**
+ * del_random_ready_callback() - Delete a previously registered readiness
+ * callback function.
+ *
+ * @rdy: callback definition that was registered initially
+ */
+void del_random_ready_callback(struct random_ready_callback *rdy)
+{
+	unsigned long flags;
+	struct module *owner = NULL;
+
+	spin_lock_irqsave(&lrng_ready_list_lock, flags);
+	if (!list_empty(&rdy->list)) {
+		list_del_init(&rdy->list);
+		owner = rdy->owner;
+	}
+	spin_unlock_irqrestore(&lrng_ready_list_lock, flags);
+
+	module_put(owner);
+}
+EXPORT_SYMBOL(del_random_ready_callback);
+
+/**
+ * add_random_ready_callback() - Add a callback function that will be invoked
+ * when the DRNG is mimimally seeded.
+ *
+ * @rdy: callback definition to be invoked when the LRNG is seeded
+ *
+ * Return:
+ * * 0 if callback is successfully added
+ * * -EALREADY if pool is already initialised (callback not called)
+ * * -ENOENT if module for callback is not alive
+ */
+int add_random_ready_callback(struct random_ready_callback *rdy)
+{
+	struct module *owner;
+	unsigned long flags;
+	int err = -EALREADY;
+
+	if (likely(lrng_state_min_seeded()))
+		return err;
+
+	owner = rdy->owner;
+	if (!try_module_get(owner))
+		return -ENOENT;
+
+	spin_lock_irqsave(&lrng_ready_list_lock, flags);
+	if (lrng_state_min_seeded())
+		goto out;
+
+	owner = NULL;
+
+	list_add(&rdy->list, &lrng_ready_list);
+	err = 0;
+
+out:
+	spin_unlock_irqrestore(&lrng_ready_list_lock, flags);
+
+	module_put(owner);
+
+	return err;
+}
+EXPORT_SYMBOL(add_random_ready_callback);
+
+/*********************** LRNG kernel output interfaces ************************/
+
+/**
+ * get_random_bytes() - Provider of cryptographic strong random numbers for
+ * kernel-internal usage.
+ *
+ * This function is appropriate for all in-kernel use cases. However,
+ * it will always use the ChaCha20 DRNG.
+ *
+ * @buf: buffer to store the random bytes
+ * @nbytes: size of the buffer
+ */
+void get_random_bytes(void *buf, int nbytes)
+{
+	lrng_drng_get_atomic((u8 *)buf, (u32)nbytes);
+	lrng_debug_report_seedlevel("get_random_bytes");
+}
+EXPORT_SYMBOL(get_random_bytes);
+
+/**
+ * get_random_bytes_full() - Provider of cryptographic strong random numbers
+ * for kernel-internal usage.
+ *
+ * This function is appropriate only for non-atomic use cases as this
+ * function may sleep. Though, it provides access to the full functionality
+ * of LRNG including the switchable DRNG support, that may support other
+ * DRNGs such as the SP800-90A DRBG.
+ *
+ * @buf: buffer to store the random bytes
+ * @nbytes: size of the buffer
+ */
+void get_random_bytes_full(void *buf, int nbytes)
+{
+	lrng_drng_get_sleep((u8 *)buf, (u32)nbytes);
+	lrng_debug_report_seedlevel("get_random_bytes_full");
+}
+EXPORT_SYMBOL(get_random_bytes_full);
+
+/**
+ * wait_for_random_bytes() - Wait for the LRNG to be seeded and thus
+ * guaranteed to supply cryptographically secure random numbers.
+ *
+ * This applies to: the /dev/urandom device, the get_random_bytes function,
+ * and the get_random_{u32,u64,int,long} family of functions. Using any of
+ * these functions without first calling this function forfeits the guarantee
+ * of security.
+ *
+ * Return:
+ * * 0 if the LRNG has been seeded.
+ * * -ERESTARTSYS if the function was interrupted by a signal.
+ */
+int wait_for_random_bytes(void)
+{
+	if (likely(lrng_state_min_seeded()))
+		return 0;
+	return wait_event_interruptible(lrng_init_wait,
+					lrng_state_min_seeded());
+}
+EXPORT_SYMBOL(wait_for_random_bytes);
+
+/**
+ * get_random_bytes_arch() - This function will use the architecture-specific
+ * hardware random number generator if it is available.
+ *
+ * The arch-specific hw RNG will almost certainly be faster than what we can
+ * do in software, but it is impossible to verify that it is implemented
+ * securely (as opposed, to, say, the AES encryption of a sequence number using
+ * a key known by the NSA).  So it's useful if we need the speed, but only if
+ * we're willing to trust the hardware manufacturer not to have put in a back
+ * door.
+ *
+ * @buf: buffer allocated by caller to store the random data in
+ * @nbytes: length of outbuf
+ *
+ * Return: number of bytes filled in.
+ */
+int __must_check get_random_bytes_arch(void *buf, int nbytes)
+{
+	u8 *p = buf;
+
+	while (nbytes) {
+		unsigned long v;
+		int chunk = min_t(int, nbytes, sizeof(unsigned long));
+
+		if (!arch_get_random_long(&v))
+			break;
+
+		memcpy(p, &v, chunk);
+		p += chunk;
+		nbytes -= chunk;
+	}
+
+	if (nbytes)
+		lrng_drng_get_atomic((u8 *)p, (u32)nbytes);
+
+	return nbytes;
+}
+EXPORT_SYMBOL(get_random_bytes_arch);
+
+/************************ LRNG user output interfaces *************************/
+
+static ssize_t lrng_read_common(char __user *buf, size_t nbytes)
+{
+	ssize_t ret = 0;
+	u8 tmpbuf[LRNG_DRNG_BLOCKSIZE] __aligned(LRNG_KCAPI_ALIGN);
+	u8 *tmp_large = NULL, *tmp = tmpbuf;
+	u32 tmplen = sizeof(tmpbuf);
+
+	if (nbytes == 0)
+		return 0;
+
+	/*
+	 * Satisfy large read requests -- as the common case are smaller
+	 * request sizes, such as 16 or 32 bytes, avoid a kmalloc overhead for
+	 * those by using the stack variable of tmpbuf.
+	 */
+	if (!IS_ENABLED(CONFIG_BASE_SMALL) && (nbytes > sizeof(tmpbuf))) {
+		tmplen = min_t(u32, nbytes, LRNG_DRNG_MAX_REQSIZE);
+		tmp_large = kmalloc(tmplen + LRNG_KCAPI_ALIGN, GFP_KERNEL);
+		if (!tmp_large)
+			tmplen = sizeof(tmpbuf);
+		else
+			tmp = PTR_ALIGN(tmp_large, LRNG_KCAPI_ALIGN);
+	}
+
+	while (nbytes) {
+		u32 todo = min_t(u32, nbytes, tmplen);
+		int rc = 0;
+
+		/* Reschedule if we received a large request. */
+		if ((tmp_large) && need_resched()) {
+			if (signal_pending(current)) {
+				if (ret == 0)
+					ret = -ERESTARTSYS;
+				break;
+			}
+			schedule();
+		}
+
+		rc = lrng_drng_get_sleep(tmp, todo);
+		if (rc <= 0) {
+			if (rc < 0)
+				ret = rc;
+			break;
+		}
+		if (copy_to_user(buf, tmp, rc)) {
+			ret = -EFAULT;
+			break;
+		}
+
+		nbytes -= rc;
+		buf += rc;
+		ret += rc;
+	}
+
+	/* Wipe data just returned from memory */
+	if (tmp_large)
+		kzfree(tmp_large);
+	else
+		memzero_explicit(tmpbuf, sizeof(tmpbuf));
+
+	return ret;
+}
+
+static ssize_t
+lrng_read_common_block(int nonblock, char __user *buf, size_t nbytes)
+{
+	if (nbytes == 0)
+		return 0;
+
+	if (unlikely(!lrng_state_operational())) {
+		int ret;
+
+		if (nonblock)
+			return -EAGAIN;
+
+		ret = wait_event_interruptible(lrng_init_wait,
+					       lrng_state_operational());
+		if (unlikely(ret))
+			return ret;
+	}
+
+	return lrng_read_common(buf, nbytes);
+}
+
+static ssize_t lrng_drng_read_block(struct file *file, char __user *buf,
+				     size_t nbytes, loff_t *ppos)
+{
+	return lrng_read_common_block(file->f_flags & O_NONBLOCK, buf, nbytes);
+}
+
+static unsigned int lrng_random_poll(struct file *file, poll_table *wait)
+{
+	__poll_t mask;
+
+	poll_wait(file, &lrng_init_wait, wait);
+	poll_wait(file, &lrng_write_wait, wait);
+	mask = 0;
+	if (lrng_state_operational())
+		mask |= EPOLLIN | EPOLLRDNORM;
+	if (lrng_need_entropy() ||
+	    lrng_state_exseed_allow(lrng_noise_source_user))
+		mask |= EPOLLOUT | EPOLLWRNORM;
+	return mask;
+}
+
+static ssize_t lrng_drng_write_common(const char __user *buffer, size_t count,
+				      u32 entropy_bits)
+{
+	ssize_t ret = 0;
+	u8 buf[64] __aligned(LRNG_KCAPI_ALIGN);
+	const char __user *p = buffer;
+	u32 orig_entropy_bits = entropy_bits;
+
+	if (!lrng_get_available())
+		return -EAGAIN;
+
+	count = min_t(size_t, count, INT_MAX);
+	while (count > 0) {
+		size_t bytes = min_t(size_t, count, sizeof(buf));
+		u32 ent = min_t(u32, bytes<<3, entropy_bits);
+
+		if (copy_from_user(&buf, p, bytes))
+			return -EFAULT;
+		/* Inject data into entropy pool */
+		lrng_pool_lfsr(buf, bytes);
+		lrng_pool_add_entropy(ent);
+
+		count -= bytes;
+		p += bytes;
+		ret += bytes;
+		entropy_bits -= ent;
+
+		cond_resched();
+	}
+
+	/* Force reseed of DRNG during next data request. */
+	if (!orig_entropy_bits)
+		lrng_drng_force_reseed();
+
+	return ret;
+}
+
+static ssize_t lrng_drng_read(struct file *file, char __user *buf,
+			      size_t nbytes, loff_t *ppos)
+{
+	if (!lrng_state_min_seeded())
+		pr_notice_ratelimited("%s - use of insufficiently seeded DRNG (%zu bytes read)\n",
+				      current->comm, nbytes);
+	else if (!lrng_state_operational())
+		pr_debug_ratelimited("%s - use of not fully seeded DRNG (%zu bytes read)\n",
+				     current->comm, nbytes);
+
+	return lrng_read_common(buf, nbytes);
+}
+
+static ssize_t lrng_drng_write(struct file *file, const char __user *buffer,
+			       size_t count, loff_t *ppos)
+{
+	return lrng_drng_write_common(buffer, count, 0);
+}
+
+static long lrng_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
+{
+	int size, ent_count_bits;
+	int __user *p = (int __user *)arg;
+
+	switch (cmd) {
+	case RNDGETENTCNT:
+		ent_count_bits = lrng_avail_entropy();
+		if (put_user(ent_count_bits, p))
+			return -EFAULT;
+		return 0;
+	case RNDADDTOENTCNT:
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+		if (get_user(ent_count_bits, p))
+			return -EFAULT;
+		ent_count_bits = (int)lrng_avail_entropy() + ent_count_bits;
+		if (ent_count_bits < 0)
+			ent_count_bits = 0;
+		if (ent_count_bits > LRNG_POOL_SIZE_BITS)
+			ent_count_bits = LRNG_POOL_SIZE_BITS;
+		lrng_pool_set_entropy(ent_count_bits);
+		return 0;
+	case RNDADDENTROPY:
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+		if (get_user(ent_count_bits, p++))
+			return -EFAULT;
+		if (ent_count_bits < 0)
+			return -EINVAL;
+		if (get_user(size, p++))
+			return -EFAULT;
+		if (size < 0)
+			return -EINVAL;
+		lrng_state_exseed_set(lrng_noise_source_user, false);
+		/* there cannot be more entropy than data */
+		ent_count_bits = min(ent_count_bits, size<<3);
+		return lrng_drng_write_common((const char __user *)p, size,
+					      ent_count_bits);
+	case RNDZAPENTCNT:
+	case RNDCLEARPOOL:
+		/* Clear the entropy pool counter. */
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+		lrng_pool_set_entropy(0);
+		return 0;
+	case RNDRESEEDCRNG:
+		/*
+		 * We leave the capability check here since it is present
+		 * in the upstream's RNG implementation. Yet, user space
+		 * can trigger a reseed as easy as writing into /dev/random
+		 * or /dev/urandom where no privilege is needed.
+		 */
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+		/* Force a reseed of all DRNGs */
+		lrng_drng_force_reseed();
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
+static int lrng_fasync(int fd, struct file *filp, int on)
+{
+	return fasync_helper(fd, filp, on, &fasync);
+}
+
+const struct file_operations random_fops = {
+	.read  = lrng_drng_read_block,
+	.write = lrng_drng_write,
+	.poll  = lrng_random_poll,
+	.unlocked_ioctl = lrng_ioctl,
+	.compat_ioctl = compat_ptr_ioctl,
+	.fasync = lrng_fasync,
+	.llseek = noop_llseek,
+};
+
+const struct file_operations urandom_fops = {
+	.read  = lrng_drng_read,
+	.write = lrng_drng_write,
+	.unlocked_ioctl = lrng_ioctl,
+	.compat_ioctl = compat_ptr_ioctl,
+	.fasync = lrng_fasync,
+	.llseek = noop_llseek,
+};
+
+SYSCALL_DEFINE3(getrandom, char __user *, buf, size_t, count,
+		unsigned int, flags)
+{
+	if (flags & ~(GRND_NONBLOCK|GRND_RANDOM|GRND_INSECURE))
+		return -EINVAL;
+
+	/*
+	 * Requesting insecure and blocking randomness at the same time makes
+	 * no sense.
+	 */
+	if ((flags &
+	     (GRND_INSECURE|GRND_RANDOM)) == (GRND_INSECURE|GRND_RANDOM))
+		return -EINVAL;
+
+	if (count > INT_MAX)
+		count = INT_MAX;
+
+	if (flags & GRND_INSECURE)
+		return lrng_drng_read(NULL, buf, count, NULL);
+
+	return lrng_read_common_block(flags & GRND_NONBLOCK, buf, count);
+}
diff --git a/drivers/char/lrng/lrng_internal.h b/drivers/char/lrng/lrng_internal.h
new file mode 100644
index 000000000000..edf38121ec65
--- /dev/null
+++ b/drivers/char/lrng/lrng_internal.h
@@ -0,0 +1,296 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
+/*
+ * Copyright (C) 2018 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#ifndef _LRNG_INTERNAL_H
+#define _LRNG_INTERNAL_H
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+
+/*************************** General LRNG parameter ***************************/
+
+/* Entropy pool parameter
+ *
+ * The LRNG_POOL_SIZE cannot be smaller than 64 bytes as the SHA-1 operation
+ * in lrng_chacha20.c requires multiples of 64 bytes
+ */
+#define LRNG_POOL_SIZE			(16 << CONFIG_LRNG_POOL_SIZE)
+#define LRNG_POOL_WORD_BYTES		(4)	/* (sizeof(atomic_t)) */
+#define LRNG_POOL_SIZE_BYTES		(LRNG_POOL_SIZE * LRNG_POOL_WORD_BYTES)
+#define LRNG_POOL_SIZE_BITS		(LRNG_POOL_SIZE_BYTES * 8)
+#define LRNG_POOL_WORD_BITS		(LRNG_POOL_WORD_BYTES * 8)
+
+/* Security strength of LRNG -- this must match DRNG security strength */
+#define LRNG_DRNG_SECURITY_STRENGTH_BYTES 32
+#define LRNG_DRNG_SECURITY_STRENGTH_BITS (LRNG_DRNG_SECURITY_STRENGTH_BYTES * 8)
+#define LRNG_DRNG_BLOCKSIZE 64		/* Maximum of DRNG block sizes */
+
+/*
+ * SP800-90A defines a maximum request size of 1<<16 bytes. The given value is
+ * considered a safer margin.
+ *
+ * This value is allowed to be changed.
+ */
+#define LRNG_DRNG_MAX_REQSIZE		(1<<12)
+
+/*
+ * SP800-90A defines a maximum number of requests between reseeds of 2^48.
+ * The given value is considered a much safer margin, balancing requests for
+ * frequent reseeds with the need to conserve entropy. This value MUST NOT be
+ * larger than INT_MAX because it is used in an atomic_t.
+ *
+ * This value is allowed to be changed.
+ */
+#define LRNG_DRNG_RESEED_THRESH		(1<<20)
+
+/*
+ * Number of interrupts to be recorded to assume that DRNG security strength
+ * bits of entropy are received.
+ * Note: a value below the DRNG security strength should not be defined as this
+ *	 may imply the DRNG can never be fully seeded in case other noise
+ *	 sources are unavailable.
+ *
+ * This value is allowed to be changed.
+ */
+#define LRNG_IRQ_ENTROPY_BITS		LRNG_DRNG_SECURITY_STRENGTH_BITS
+
+/*
+ * Min required seed entropy is 128 bits covering the minimum entropy
+ * requirement of SP800-131A and the German BSI's TR02102.
+ *
+ * This value is allowed to be changed.
+ */
+#define LRNG_FULL_SEED_ENTROPY_BITS	LRNG_DRNG_SECURITY_STRENGTH_BITS
+#define LRNG_MIN_SEED_ENTROPY_BITS	128
+#define LRNG_INIT_ENTROPY_BITS		32
+
+/*
+ * Amount of entropy that is lost with the conditioning functions of LFSR and
+ * hash_df as shown with the entropy analysis compliant to SP800-90B.
+ */
+#define LRNG_CONDITIONING_ENTROPY_LOSS	1
+
+/*
+ * Wakeup value
+ *
+ * This value is allowed to be changed.
+ */
+#if (LRNG_POOL_SIZE_BITS <= (LRNG_DRNG_SECURITY_STRENGTH_BITS * 2))
+# define LRNG_WRITE_WAKEUP_ENTROPY	(LRNG_DRNG_SECURITY_STRENGTH_BITS + \
+					LRNG_CONDITIONING_ENTROPY_LOSS)
+#else
+# define LRNG_WRITE_WAKEUP_ENTROPY	(LRNG_DRNG_SECURITY_STRENGTH_BITS * 2)
+#endif
+
+/*
+ * Oversampling factor of IRQ events to obtain
+ * LRNG_DRNG_SECURITY_STRENGTH_BYTES. This factor is used when a
+ * high-resolution time stamp is not available. In this case, jiffies and
+ * register contents are used to fill the entropy pool. These noise sources
+ * are much less entropic than the high-resolution timer. The entropy content
+ * is the entropy content assumed with LRNG_IRQ_ENTROPY_BITS divided by
+ * LRNG_IRQ_OVERSAMPLING_FACTOR.
+ *
+ * This value is allowed to be changed.
+ */
+#define LRNG_IRQ_OVERSAMPLING_FACTOR	10
+
+/*
+ * Alignmask which should cover all cipher implementations
+ * WARNING: If this is changed to a value larger than 8, manual
+ * alignment is necessary as older versions of GCC may not be capable
+ * of aligning stack variables at boundaries greater than 8.
+ * In this case, PTR_ALIGN must be used.
+ */
+#define LRNG_KCAPI_ALIGN		8
+
+/************************ Default DRNG implementation *************************/
+
+extern struct chacha20_state chacha20;
+extern const struct lrng_crypto_cb lrng_cc20_crypto_cb;
+void lrng_cc20_init_state(struct chacha20_state *state);
+
+/********************************** /proc *************************************/
+
+static inline void lrng_pool_inc_numa_node(void) { }
+
+/****************************** LRNG interfaces *******************************/
+
+extern u32 lrng_write_wakeup_bits;
+extern int lrng_drng_reseed_max_time;
+
+void lrng_writer_wakeup(void);
+void lrng_init_wakeup(void);
+void lrng_debug_report_seedlevel(const char *name);
+void lrng_process_ready_list(void);
+
+/************************** Entropy pool management ***************************/
+
+enum lrng_external_noise_source {
+	lrng_noise_source_hw,
+	lrng_noise_source_user
+};
+
+bool lrng_state_exseed_allow(enum lrng_external_noise_source source);
+void lrng_state_exseed_set(enum lrng_external_noise_source source, bool type);
+void lrng_state_init_seed_work(void);
+u32 lrng_avail_entropy(void);
+void lrng_set_entropy_thresh(u32 new);
+int lrng_pool_trylock(void);
+void lrng_pool_unlock(void);
+void lrng_reset_state(void);
+void lrng_pool_all_numa_nodes_seeded(void);
+bool lrng_state_min_seeded(void);
+bool lrng_state_fully_seeded(void);
+bool lrng_state_operational(void);
+bool lrng_pool_highres_timer(void);
+void lrng_pool_set_entropy(u32 entropy_bits);
+void lrng_pool_lfsr(const u8 *buf, u32 buflen);
+void lrng_pool_lfsr_nonaligned(const u8 *buf, u32 buflen);
+void lrng_pool_lfsr_u32(u32 value);
+void lrng_pool_add_irq(u32 irq_num);
+void lrng_pool_add_entropy(u32 entropy_bits);
+
+struct entropy_buf {
+	u8 a[LRNG_DRNG_SECURITY_STRENGTH_BYTES];
+	u8 b[LRNG_DRNG_SECURITY_STRENGTH_BYTES];
+	u8 c[LRNG_DRNG_SECURITY_STRENGTH_BYTES];
+	u32 now;
+};
+
+int lrng_fill_seed_buffer(const struct lrng_crypto_cb *crypto_cb, void *hash,
+			  struct entropy_buf *entropy_buf, u32 entropy_retain);
+void lrng_init_ops(u32 seed_bits);
+
+/************************** Jitter RNG Noise Source ***************************/
+
+#ifdef CONFIG_LRNG_JENT
+u32 lrng_get_jent(u8 *outbuf, unsigned int outbuflen);
+u32 lrng_jent_entropylevel(void);
+#else /* CONFIG_CRYPTO_JITTERENTROPY */
+static inline u32 lrng_get_jent(u8 *outbuf, unsigned int outbuflen) {return 0; }
+static inline u32 lrng_jent_entropylevel(void) { return 0; }
+#endif /* CONFIG_CRYPTO_JITTERENTROPY */
+
+/*************************** CPU-based Noise Source ***************************/
+
+u32 lrng_get_arch(u8 *outbuf);
+u32 lrng_slow_noise_req_entropy(u32 required_entropy_bits);
+
+/****************************** DRNG processing *******************************/
+
+/* Secondary DRNG state handle */
+struct lrng_drng {
+	void *drng;				/* DRNG handle */
+	void *hash;				/* Hash handle */
+	const struct lrng_crypto_cb *crypto_cb;	/* Crypto callbacks */
+	atomic_t requests;			/* Number of DRNG requests */
+	unsigned long last_seeded;		/* Last time it was seeded */
+	bool fully_seeded;			/* Is DRNG fully seeded? */
+	bool force_reseed;			/* Force a reseed */
+	struct mutex lock;
+	spinlock_t spin_lock;
+};
+
+extern struct mutex lrng_crypto_cb_update;
+
+struct lrng_drng *lrng_drng_init_instance(void);
+struct lrng_drng *lrng_drng_atomic_instance(void);
+
+static __always_inline bool lrng_drng_is_atomic(struct lrng_drng *drng)
+{
+	return (drng->drng == lrng_drng_atomic_instance()->drng);
+}
+
+/* Lock the DRNG */
+static __always_inline void lrng_drng_lock(struct lrng_drng *drng,
+					   unsigned long *flags)
+{
+	/* Use spin lock in case the atomic DRNG context is used */
+	if (lrng_drng_is_atomic(drng)) {
+		spin_lock_irqsave(&drng->spin_lock, *flags);
+
+		/*
+		 * In case a lock transition happened while we were spinning,
+		 * catch this case and use the new lock type.
+		 */
+		if (!lrng_drng_is_atomic(drng)) {
+			spin_unlock_irqrestore(&drng->spin_lock, *flags);
+			mutex_lock(&drng->lock);
+		}
+	} else {
+		mutex_lock(&drng->lock);
+	}
+}
+
+/* Unlock the DRNG */
+static __always_inline void lrng_drng_unlock(struct lrng_drng *drng,
+					     unsigned long *flags)
+{
+	if (lrng_drng_is_atomic(drng))
+		spin_unlock_irqrestore(&drng->spin_lock, *flags);
+	else
+		mutex_unlock(&drng->lock);
+}
+
+bool lrng_get_available(void);
+void lrng_set_available(void);
+void lrng_drngs_init_cc20(void);
+void lrng_drng_reset(struct lrng_drng *drng);
+int lrng_drng_get_atomic(u8 *outbuf, u32 outbuflen);
+int lrng_drng_get_sleep(u8 *outbuf, u32 outbuflen);
+void lrng_drng_force_reseed(void);
+void lrng_drng_seed_work(struct work_struct *dummy);
+
+static inline struct lrng_drng **lrng_drng_instances(void) { return NULL; }
+static inline void lrng_drngs_numa_alloc(void) { return; }
+
+/************************** Health Test linking code **************************/
+
+enum lrng_health_res {
+	lrng_health_pass,		/* Health test passes on time stamp */
+	lrng_health_fail_use,		/* Time stamp unhealthy, but mix in */
+	lrng_health_fail_drop		/* Time stamp unhealthy, drop it */
+};
+
+#ifdef CONFIG_LRNG_HEALTH_TESTS
+bool lrng_sp80090b_startup_complete(void);
+bool lrng_sp80090b_compliant(void);
+
+enum lrng_health_res lrng_health_test(u32 now_time);
+void lrng_health_disable(void);
+
+void lrng_reset(void);
+#else	/* CONFIG_LRNG_HEALTH_TESTS */
+static inline bool lrng_sp80090b_startup_complete(void) { return true; }
+static inline bool lrng_sp80090b_compliant(void) { return false; }
+
+static inline enum lrng_health_res
+lrng_health_test(u32 now_time) { return lrng_health_pass; }
+static inline void lrng_health_disable(void) { }
+#endif	/* CONFIG_LRNG_HEALTH_TESTS */
+
+/****************************** Helper code ***********************************/
+
+static inline u32 atomic_read_u32(atomic_t *v)
+{
+	return (u32)atomic_read(v);
+}
+
+/*************************** Auxiliary functions ******************************/
+
+void invalidate_batched_entropy(void);
+
+/***************************** Testing code ***********************************/
+
+#ifdef CONFIG_LRNG_TESTING
+bool lrng_raw_entropy_store(u32 value);
+#else	/* CONFIG_LRNG_TESTING */
+static inline bool lrng_raw_entropy_store(u32 value) { return false; }
+#endif	/* CONFIG_LRNG_TESTING */
+
+#endif /* _LRNG_INTERNAL_H */
diff --git a/drivers/char/lrng/lrng_lfsr.h b/drivers/char/lrng/lrng_lfsr.h
new file mode 100644
index 000000000000..f0e38a0aadfd
--- /dev/null
+++ b/drivers/char/lrng/lrng_lfsr.h
@@ -0,0 +1,152 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
+/*
+ * LRNG Linear Feedback Shift Register
+ *
+ * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+/* Status information about IRQ noise source */
+struct lrng_irq_info {
+	atomic_t num_events;	/* Number of healthy IRQs since last read */
+	atomic_t num_events_thresh;	/* Reseed threshold */
+	atomic_t reseed_in_progress;	/* Flag for on executing reseed */
+	bool irq_highres_timer;	/* Is high-resolution timer available? */
+	u32 irq_entropy_bits;	/* LRNG_IRQ_ENTROPY_BITS? */
+};
+
+/*
+ * This is the entropy pool used by the slow noise source. Its size should
+ * be at least as large as LRNG_DRNG_SECURITY_STRENGTH_BITS.
+ *
+ * The pool array is aligned to 8 bytes to comfort the kernel crypto API cipher
+ * implementations of the hash functions used to read the pool: for some
+ * accelerated implementations, we need an alignment to avoid a realignment
+ * which involves memcpy(). The alignment to 8 bytes should satisfy all crypto
+ * implementations.
+ *
+ * LRNG_POOL_SIZE is allowed to be changed only if the taps of the polynomial
+ * used for the LFSR are changed as well. The size must be in powers of 2 due
+ * to the mask handling in lrng_pool_lfsr_u32 which uses AND instead of modulo.
+ */
+struct lrng_pool {
+	union {
+		struct {
+			/*
+			 * hash_df implementation: counter, requested_bits and
+			 * pool form a linear buffer that is used in the
+			 * hash_df function specified in SP800-90A section
+			 * 10.3.1
+			 */
+			unsigned char counter;
+			__be32 requested_bits;
+
+			/* Pool */
+			atomic_t pool[LRNG_POOL_SIZE];
+			/* Ptr into pool for next IRQ word injection */
+			atomic_t pool_ptr;
+			/* rotate for LFSR */
+			atomic_t input_rotate;
+			/* All NUMA DRNGs seeded? */
+			bool all_online_numa_node_seeded;
+			/* IRQ noise source status info */
+			struct lrng_irq_info irq_info;
+			/* Serialize read of entropy pool */
+			spinlock_t lock;
+		};
+		/*
+		 * Static SHA-1 implementation in lrng_cc20_hash_buffer
+		 * processes data 64-byte-wise. Hence, ensure proper size
+		 * of LRNG entropy pool data structure.
+		 */
+		u8 hash_input_buf[LRNG_POOL_SIZE_BYTES + 64];
+	};
+};
+
+/*
+ * Implement a (modified) twisted Generalized Feedback Shift Register. (See M.
+ * Matsumoto & Y. Kurita, 1992.  Twisted GFSR generators. ACM Transactions on
+ * Modeling and Computer Simulation 2(3):179-194.  Also see M. Matsumoto & Y.
+ * Kurita, 1994.  Twisted GFSR generators II.  ACM Transactions on Modeling and
+ * Computer Simulation 4:254-266).
+ */
+static u32 const lrng_twist_table[8] = {
+	0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158,
+	0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 };
+
+/*
+ * The polynomials for the LFSR are taken from the document "Table of Linear
+ * Feedback Shift Registers" by Roy Ward, Tim Molteno, October 26, 2007.
+ * The first polynomial is from "Primitive Binary Polynomials" by Wayne
+ * Stahnke (1973) and is primitive as well as irreducible.
+ *
+ * Note, the tap values are smaller by one compared to the documentation because
+ * they are used as an index into an array where the index starts by zero.
+ *
+ * All polynomials were also checked to be primitive and irreducible with magma
+ * which ensures that the key property of the LFSR providing a compression
+ * function for entropy is guaranteed.
+ */
+static u32 const lrng_lfsr_polynomial[][4] = {
+	{ 15, 13, 12, 10 },			/* 16 words */
+	{ 31, 29, 25, 24 },			/* 32 words */
+	{ 63, 62, 60, 59 },			/* 64 words */
+	{ 127, 28, 26, 1 },			/* 128 words by Stahnke */
+	{ 255, 253, 250, 245 },			/* 256 words */
+	{ 511, 509, 506, 503 },			/* 512 words */
+	{ 1023, 1014, 1001, 1000 },		/* 1024 words */
+	{ 2047, 2034, 2033, 2028 },		/* 2048 words */
+	{ 4095, 4094, 4080, 4068 },		/* 4096 words */
+};
+
+static inline void _lrng_pool_lfsr_u32(struct lrng_pool *pool, u32 value)
+{
+	/*
+	 * Process the LFSR by altering not adjacent words but rather
+	 * more spaced apart words. Using a prime number ensures that all words
+	 * are processed evenly. As some the LFSR polynomials taps are close
+	 * together, processing adjacent words with the LSFR taps may be
+	 * inappropriate as the data just mixed-in at these taps may be not
+	 * independent from the current data to be mixed in.
+	 */
+	u32 ptr = (u32)atomic_add_return_relaxed(67, &pool->pool_ptr) &
+							(LRNG_POOL_SIZE - 1);
+	/*
+	 * Add 7 bits of rotation to the pool. At the beginning of the
+	 * pool, add an extra 7 bits rotation, so that successive passes
+	 * spread the input bits across the pool evenly.
+	 *
+	 * Note, there is a race between getting ptr and calculating
+	 * input_rotate when ptr is is obtained on two or more CPUs at the
+	 * same time. This race is irrelevant as it may only come into effect
+	 * if 3 or more CPUs race at the same time which is very unlikely. If
+	 * the race happens, it applies to one event only. As this rolling
+	 * supports the LFSR without being strictly needed, we accept this
+	 * race.
+	 */
+	u32 input_rotate = (u32)atomic_add_return_relaxed((ptr ? 7 : 14),
+					&pool->input_rotate) & 31;
+	u32 word = rol32(value, input_rotate);
+
+	BUILD_BUG_ON(LRNG_POOL_WORD_BYTES != sizeof(pool->pool[0]));
+	BUILD_BUG_ON(LRNG_POOL_SIZE - 1 !=
+		     lrng_lfsr_polynomial[CONFIG_LRNG_POOL_SIZE][0]);
+	word ^= atomic_read_u32(&pool->pool[ptr]);
+	word ^= atomic_read_u32(&pool->pool[
+		(ptr + lrng_lfsr_polynomial[CONFIG_LRNG_POOL_SIZE][0]) &
+		       (LRNG_POOL_SIZE - 1)]);
+	word ^= atomic_read_u32(&pool->pool[
+		(ptr + lrng_lfsr_polynomial[CONFIG_LRNG_POOL_SIZE][1]) &
+		       (LRNG_POOL_SIZE - 1)]);
+	word ^= atomic_read_u32(&pool->pool[
+		(ptr + lrng_lfsr_polynomial[CONFIG_LRNG_POOL_SIZE][2]) &
+		       (LRNG_POOL_SIZE - 1)]);
+	word ^= atomic_read_u32(&pool->pool[
+		(ptr + lrng_lfsr_polynomial[CONFIG_LRNG_POOL_SIZE][3]) &
+		       (LRNG_POOL_SIZE - 1)]);
+
+	word = (word >> 3) ^ lrng_twist_table[word & 7];
+	atomic_set(&pool->pool[ptr], word);
+}
+
+u32 __lrng_pool_hash_df(const struct lrng_crypto_cb *crypto_cb, void *hash,
+			struct lrng_pool *pool, u8 *outbuf, u32 requested_bits);
diff --git a/drivers/char/lrng/lrng_pool.c b/drivers/char/lrng/lrng_pool.c
new file mode 100644
index 000000000000..5ef2f164d737
--- /dev/null
+++ b/drivers/char/lrng/lrng_pool.c
@@ -0,0 +1,586 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG Entropy pool management
+ *
+ * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <asm/irq_regs.h>
+#include <linux/lrng.h>
+#include <linux/percpu.h>
+#include <linux/random.h>
+#include <linux/utsname.h>
+#include <linux/workqueue.h>
+
+#include "lrng_internal.h"
+#include "lrng_lfsr.h"
+
+struct lrng_state {
+	bool lrng_operational;		/* Is DRNG operational? */
+	bool lrng_fully_seeded;		/* Is DRNG fully seeded? */
+	bool lrng_min_seeded;		/* Is DRNG minimally seeded? */
+
+	/*
+	 * To ensure that external entropy providers cannot dominate the
+	 * internal noise sources but yet cannot be dominated by internal
+	 * noise sources, the following booleans are intended to allow
+	 * external to provide seed once when a DRNG reseed occurs. This
+	 * triggering of external noise source is performed even when the
+	 * entropy pool has sufficient entropy.
+	 */
+	bool lrng_seed_hw;		/* Allow HW to provide seed */
+	bool lrng_seed_user;		/* Allow user space to provide seed */
+
+	struct work_struct lrng_seed_work;	/* (re)seed work queue */
+};
+
+static struct lrng_pool lrng_pool __aligned(LRNG_KCAPI_ALIGN) = {
+	.irq_info	= {
+		.irq_entropy_bits	= LRNG_IRQ_ENTROPY_BITS,
+		.num_events_thresh	= ATOMIC_INIT(LRNG_INIT_ENTROPY_BITS +
+						LRNG_CONDITIONING_ENTROPY_LOSS),
+		/* Sample IRQ pointer data at least during boot */
+		.irq_highres_timer	= false },
+	.lock		= __SPIN_LOCK_UNLOCKED(lrng_pool.lock)
+};
+
+static struct lrng_state lrng_state = { false, false, false, true, true };
+
+/********************************** Helper ***********************************/
+
+/* External entropy provider is allowed to provide seed data */
+bool lrng_state_exseed_allow(enum lrng_external_noise_source source)
+{
+	if (source == lrng_noise_source_hw)
+		return lrng_state.lrng_seed_hw;
+	return lrng_state.lrng_seed_user;
+}
+
+/* Enable / disable external entropy provider to furnish seed */
+void lrng_state_exseed_set(enum lrng_external_noise_source source, bool type)
+{
+	if (source == lrng_noise_source_hw)
+		lrng_state.lrng_seed_hw = type;
+	else
+		lrng_state.lrng_seed_user = type;
+}
+
+static inline void lrng_state_exseed_allow_all(void)
+{
+	lrng_state_exseed_set(lrng_noise_source_hw, true);
+	lrng_state_exseed_set(lrng_noise_source_user, true);
+}
+
+void lrng_state_init_seed_work(void)
+{
+	INIT_WORK(&lrng_state.lrng_seed_work, lrng_drng_seed_work);
+}
+
+static inline u32 lrng_entropy_to_data(u32 entropy_bits)
+{
+	return ((entropy_bits * lrng_pool.irq_info.irq_entropy_bits) /
+		LRNG_DRNG_SECURITY_STRENGTH_BITS);
+}
+
+static inline u32 lrng_data_to_entropy(u32 irqnum)
+{
+	return ((irqnum * LRNG_DRNG_SECURITY_STRENGTH_BITS) /
+		lrng_pool.irq_info.irq_entropy_bits);
+}
+
+u32 lrng_avail_entropy(void)
+{
+	return min_t(u32, LRNG_POOL_SIZE_BITS, lrng_data_to_entropy(
+			atomic_read_u32(&lrng_pool.irq_info.num_events)));
+}
+
+void lrng_set_entropy_thresh(u32 new)
+{
+	atomic_set(&lrng_pool.irq_info.num_events_thresh,
+		   lrng_entropy_to_data(new));
+}
+
+/*
+ * Reading of the LRNG pool is only allowed by one caller. The reading is
+ * only performed to (re)seed DRNGs. Thus, if this "lock" is already taken,
+ * the reseeding operation is in progress. The caller is not intended to wait
+ * but continue with its other operation.
+ */
+int lrng_pool_trylock(void)
+{
+	return atomic_cmpxchg(&lrng_pool.irq_info.reseed_in_progress, 0, 1);
+}
+
+void lrng_pool_unlock(void)
+{
+	atomic_set(&lrng_pool.irq_info.reseed_in_progress, 0);
+}
+
+void lrng_reset_state(void)
+{
+	struct lrng_irq_info *irq_info = &lrng_pool.irq_info;
+
+	atomic_set(&irq_info->num_events, 0);
+	lrng_state.lrng_operational = false;
+	lrng_state.lrng_fully_seeded = false;
+	lrng_state.lrng_min_seeded = false;
+	lrng_pool.all_online_numa_node_seeded = false;
+	pr_debug("reset LRNG\n");
+}
+
+void lrng_pool_all_numa_nodes_seeded(void)
+{
+	lrng_pool.all_online_numa_node_seeded = true;
+}
+
+bool lrng_state_min_seeded(void)
+{
+	return lrng_state.lrng_min_seeded;
+}
+
+bool lrng_state_fully_seeded(void)
+{
+	return lrng_state.lrng_fully_seeded;
+}
+
+bool lrng_state_operational(void)
+{
+	return lrng_state.lrng_operational;
+}
+
+bool lrng_pool_highres_timer(void)
+{
+	return lrng_pool.irq_info.irq_highres_timer;
+}
+
+void lrng_pool_set_entropy(u32 entropy_bits)
+{
+	atomic_set(&lrng_pool.irq_info.num_events,
+		   lrng_entropy_to_data(entropy_bits));
+}
+
+static void lrng_pool_configure(bool highres_timer, u32 irq_entropy_bits)
+{
+	struct lrng_irq_info *irq_info = &lrng_pool.irq_info;
+
+	irq_info->irq_highres_timer = highres_timer;
+	if (irq_info->irq_entropy_bits != irq_entropy_bits) {
+		irq_info->irq_entropy_bits = irq_entropy_bits;
+		/* Reset the threshold based on new oversampling factor. */
+		lrng_set_entropy_thresh(atomic_read_u32(
+						&irq_info->num_events_thresh));
+	}
+}
+
+static int __init lrng_init_time_source(void)
+{
+	if (random_get_entropy() || random_get_entropy()) {
+		/*
+		 * As the highres timer is identified here, previous interrupts
+		 * obtained during boot time are treated like a lowres-timer
+		 * would have been present.
+		 */
+		lrng_pool_configure(true, LRNG_IRQ_ENTROPY_BITS);
+	} else {
+		lrng_health_disable();
+		lrng_pool_configure(false, LRNG_IRQ_ENTROPY_BITS *
+					   LRNG_IRQ_OVERSAMPLING_FACTOR);
+		pr_warn("operating without high-resolution timer and applying IRQ oversampling factor %u\n",
+			LRNG_IRQ_OVERSAMPLING_FACTOR);
+	}
+
+	return 0;
+}
+
+core_initcall(lrng_init_time_source);
+
+/* invoke function with buffer aligned to 4 bytes */
+void lrng_pool_lfsr(const u8 *buf, u32 buflen)
+{
+	u32 *p_buf = (u32 *)buf;
+
+	for (; buflen >= 4; buflen -= 4)
+		lrng_pool_lfsr_u32(*p_buf++);
+
+	buf = (u8 *)p_buf;
+	while (buflen--)
+		lrng_pool_lfsr_u32(*buf++);
+}
+
+void lrng_pool_lfsr_nonaligned(const u8 *buf, u32 buflen)
+{
+	while (buflen) {
+		if (!((unsigned long)buf & (sizeof(u32) - 1))) {
+			lrng_pool_lfsr(buf, buflen);
+			return;
+		}
+
+		lrng_pool_lfsr_u32(*buf++);
+		buflen--;
+	}
+}
+
+/**************************** Interrupt processing ****************************/
+
+/*
+ * Hot code path - inject data into entropy pool using LFSR
+ */
+void lrng_pool_lfsr_u32(u32 value)
+{
+	_lrng_pool_lfsr_u32(&lrng_pool, value);
+}
+
+/*
+ * Hot code path - mix data into entropy pool
+ */
+void lrng_pool_add_irq(u32 irq_num)
+{
+	struct lrng_irq_info *irq_info = &lrng_pool.irq_info;
+
+	atomic_add(irq_num, &irq_info->num_events);
+
+	/*
+	 * Once all DRNGs are fully seeded, the interrupt noise
+	 * sources will not trigger any reseeding any more.
+	 */
+	if (likely(lrng_pool.all_online_numa_node_seeded))
+		return;
+
+	/* Only try to reseed if the DRNG is alive. */
+	if (!lrng_get_available())
+		return;
+
+	/* Only trigger the DRNG reseed if we have collected enough IRQs. */
+	if (atomic_read_u32(&lrng_pool.irq_info.num_events) <
+	    atomic_read_u32(&lrng_pool.irq_info.num_events_thresh))
+		return;
+
+	/* Ensure that the seeding only occurs once at any given time. */
+	if (lrng_pool_trylock())
+		return;
+
+	/* Seed the DRNG with IRQ noise. */
+	schedule_work(&lrng_state.lrng_seed_work);
+}
+
+void lrng_pool_add_entropy(u32 entropy_bits)
+{
+	lrng_pool_add_irq(lrng_entropy_to_data(entropy_bits));
+}
+
+/*
+ * Generate a hashed output of pool using the SP800-90A section 10.3.1 hash_df
+ * function
+ */
+u32 __lrng_pool_hash_df(const struct lrng_crypto_cb *crypto_cb, void *hash,
+			struct lrng_pool *pool, u8 *outbuf, u32 requested_bits)
+{
+	u32 digestsize, requested_bytes = requested_bits >> 3,
+	    generated_bytes = 0;
+	u8 digest[64] __aligned(LRNG_KCAPI_ALIGN);
+
+	digestsize = crypto_cb->lrng_hash_digestsize(hash);
+	if (digestsize > sizeof(digest)) {
+		pr_err("Digest buffer too small\n");
+		return 0;
+	}
+
+	pool->counter = 1;
+	pool->requested_bits = cpu_to_be32(requested_bytes << 3);
+
+	while (requested_bytes) {
+		u32 tocopy = min_t(u32, requested_bytes, digestsize);
+
+		/* The counter must not wrap */
+		if (pool->counter == 0)
+			goto out;
+
+		if (crypto_cb->lrng_hash_buffer(hash, (u8 *)pool,
+						LRNG_POOL_SIZE_BYTES + 64,
+						digest))
+			goto out;
+
+		/* Copy the data out to the caller */
+		memcpy(outbuf + generated_bytes, digest, tocopy);
+		requested_bytes -= tocopy;
+		generated_bytes += tocopy;
+		pool->counter++;
+	}
+
+out:
+	/* Mix read data back into pool for backtracking resistance */
+	if (generated_bytes)
+		lrng_pool_lfsr(outbuf, generated_bytes);
+	memzero_explicit(digest, digestsize);
+	return (generated_bytes<<3);
+}
+
+static inline u32 lrng_pool_hash_df(const struct lrng_crypto_cb *crypto_cb,
+				    void *hash, u8 *outbuf, u32 requested_bits)
+{
+	return __lrng_pool_hash_df(crypto_cb, hash, &lrng_pool, outbuf,
+				   requested_bits);
+}
+
+/**
+ * lrng_get_pool() - Read the entropy pool out for use.
+ *
+ * This function handles the translation from the number of received interrupts
+ * into an entropy statement. The conversion depends on LRNG_IRQ_ENTROPY_BITS
+ * which defines how many interrupts must be received to obtain 256 bits of
+ * entropy. With this value, the function lrng_data_to_entropy converts a given
+ * data size (received interrupts, requested amount of data, etc.) into an
+ * entropy statement. lrng_entropy_to_data does the reverse.
+ *
+ * Both functions are agnostic about the type of data: when the number of
+ * interrupts is processed by these functions, the resulting entropy value is in
+ * bits as we assume the entropy of interrupts is measured in bits. When data is
+ * processed, the entropy value is in bytes as the data is measured in bytes.
+ *
+ * @outbuf: buffer to store data in with size LRNG_DRNG_SECURITY_STRENGTH_BYTES
+ * @requested_entropy_bits: requested bits of entropy -- the function will
+ *			    return at least this amount of entropy if available
+ * @entropy_retain: amount of entropy in bits that should be left in the pool
+ *
+ * Return: estimated entropy from the IRQs that was obtained
+ */
+static u32 lrng_get_pool(const struct lrng_crypto_cb *crypto_cb, void *hash,
+			 u8 *outbuf, u32 requested_entropy_bits,
+			 u32 entropy_retain)
+{
+	struct lrng_pool *pool = &lrng_pool;
+	struct lrng_state *state = &lrng_state;
+	struct lrng_irq_info *irq_info = &pool->irq_info;
+	unsigned long flags;
+
+	u32 irq_num_events_used, irq_num_events, avail_entropy_bits;
+
+	/* This get_pool operation must only be called once at a given time! */
+	spin_lock_irqsave(&pool->lock, flags);
+
+	/* How many unused interrupts are in entropy pool? */
+	irq_num_events = atomic_read_u32(&irq_info->num_events);
+	/* Convert available interrupts into entropy statement */
+	avail_entropy_bits = lrng_data_to_entropy(irq_num_events);
+
+	/* Cap available entropy to pool size */
+	avail_entropy_bits =
+			min_t(u32, avail_entropy_bits, LRNG_POOL_SIZE_BITS);
+
+	/* How much entropy we need to and can we use? */
+	if (unlikely(!state->lrng_fully_seeded)) {
+		/*
+		 * During boot time, we read 256 bits data with
+		 * avail_entropy_bits entropy. In case our conservative
+		 * entropy estimate underestimates the available entropy
+		 * we can transport as much available entropy as
+		 * possible. The entropy pool does not operate compliant to
+		 * the German AIS 21/31 NTG.1 yet.
+		 */
+		requested_entropy_bits =
+				LRNG_DRNG_SECURITY_STRENGTH_BITS;
+	} else {
+		/* Provide all entropy above retaining level */
+		if (avail_entropy_bits < entropy_retain) {
+			requested_entropy_bits = 0;
+			goto out;
+		}
+		avail_entropy_bits -= entropy_retain;
+		requested_entropy_bits = min_t(u32, avail_entropy_bits,
+					       requested_entropy_bits);
+	}
+
+	/* Hash is a compression function: we generate entropy amount of data */
+	requested_entropy_bits = round_down(requested_entropy_bits, 8);
+
+	requested_entropy_bits = lrng_pool_hash_df(crypto_cb, hash, outbuf,
+						   requested_entropy_bits);
+
+	/* Boot time: After getting the full buffer adjust the entropy value. */
+	requested_entropy_bits = min_t(u32, avail_entropy_bits,
+				       requested_entropy_bits);
+
+out:
+	/* Convert used entropy into interrupt number for subtraction */
+	irq_num_events_used = lrng_entropy_to_data(requested_entropy_bits);
+
+	/*
+	 * The hash_df operation entropy assessment shows that the output
+	 * entropy is one bit smaller than the input entropy. Therefore we
+	 * account for this one bit of entropy here: if we have sufficient
+	 * entropy in the LFSR, we say we used one bit of entropy more.
+	 * Otherwise we reduce the amount of entropy we say we generated with
+	 * the hash_df.
+	 */
+	if (irq_num_events_used) {
+		if ((irq_num_events_used + LRNG_CONDITIONING_ENTROPY_LOSS) <=
+		    lrng_entropy_to_data(avail_entropy_bits)) {
+			irq_num_events_used += LRNG_CONDITIONING_ENTROPY_LOSS;
+		} else {
+			if (unlikely(requested_entropy_bits <
+				     LRNG_CONDITIONING_ENTROPY_LOSS))
+				requested_entropy_bits = 0;
+			else
+				requested_entropy_bits -=
+						LRNG_CONDITIONING_ENTROPY_LOSS;
+		}
+	}
+
+	/*
+	 * New events might have arrived in the meanwhile and we don't
+	 * want to throw them away unconditionally. On the other hand,
+	 * these new events might have been mixed in before
+	 * lrng_hash_df_pool() had been able to draw any entropy
+	 * from the pool and thus, the pool capacity might have been
+	 * exceeded at some point. Note that in theory, some events
+	 * might get lost inbetween the atomic_read() and
+	 * atomic_set() below. But that's fine, because it's no real
+	 * concern while code preventing this would come at the cost of
+	 * additional complexity. Likewise, some events which arrived
+	 * after full or partial completion of the __lrng_hash_df_pool()
+	 * above might get unnecessarily thrown away by the min()
+	 * operation below; the same argument applies there.
+	 */
+	irq_num_events = atomic_read_u32(&irq_info->num_events);
+	irq_num_events = min_t(u32, irq_num_events,
+			       lrng_entropy_to_data(LRNG_POOL_SIZE_BITS));
+	irq_num_events -= irq_num_events_used;
+	atomic_set(&irq_info->num_events, irq_num_events);
+
+	spin_unlock_irqrestore(&pool->lock, flags);
+
+	/* Obtain entropy statement in bits from the used entropy */
+	pr_debug("obtained %u bits of entropy from %u newly collected interrupts - not using %u interrupts\n",
+		 requested_entropy_bits, irq_num_events_used,
+		 irq_num_events);
+
+	return requested_entropy_bits;
+}
+
+/* Fill the seed buffer with data from the noise sources */
+int lrng_fill_seed_buffer(const struct lrng_crypto_cb *crypto_cb, void *hash,
+			  struct entropy_buf *entropy_buf, u32 entropy_retain)
+{
+	struct lrng_state *state = &lrng_state;
+	u32 total_entropy_bits = 0;
+
+	/* Require at least 128 bits of entropy for any reseed. */
+	if (state->lrng_fully_seeded &&
+	    (lrng_avail_entropy() <
+	     lrng_slow_noise_req_entropy(LRNG_MIN_SEED_ENTROPY_BITS +
+					 LRNG_CONDITIONING_ENTROPY_LOSS) +
+	      entropy_retain))
+		goto wakeup;
+
+	/*
+	 * Concatenate the output of the noise sources. This would be the
+	 * spot to add an entropy extractor logic if desired. Note, this
+	 * has the ability to collect entropy equal or larger than the DRNG
+	 * strength.
+	 */
+	total_entropy_bits = lrng_get_pool(crypto_cb, hash, entropy_buf->a,
+					   LRNG_DRNG_SECURITY_STRENGTH_BITS,
+					   entropy_retain);
+	total_entropy_bits += lrng_get_arch(entropy_buf->b);
+	total_entropy_bits += lrng_get_jent(entropy_buf->c,
+					    LRNG_DRNG_SECURITY_STRENGTH_BYTES);
+
+	/* also reseed the DRNG with the current time stamp */
+	entropy_buf->now = random_get_entropy();
+
+	/* allow external entropy provider to provide seed */
+	lrng_state_exseed_allow_all();
+
+wakeup:
+	/*
+	 * Shall we wake up user space writers? This location covers
+	 * ensures that the user space provider does not dominate the internal
+	 * noise sources since in case the first call of this function finds
+	 * sufficient entropy in the entropy pool, it will not trigger the
+	 * wakeup. This implies that when the next /dev/urandom read happens,
+	 * the entropy pool is drained.
+	 */
+	lrng_writer_wakeup();
+
+	return total_entropy_bits;
+}
+
+/**
+ * lrng_init_ops() - Set seed stages of LRNG
+ *
+ * Set the slow noise source reseed trigger threshold. The initial threshold
+ * is set to the minimum data size that can be read from the pool: a word. Upon
+ * reaching this value, the next seed threshold of 128 bits is set followed
+ * by 256 bits.
+ *
+ * @entropy_bits: size of entropy currently injected into DRNG
+ */
+void lrng_init_ops(u32 seed_bits)
+{
+	struct lrng_state *state = &lrng_state;
+
+	if (state->lrng_operational)
+		return;
+
+	/* DRNG is seeded with full security strength */
+	if (state->lrng_fully_seeded) {
+		state->lrng_operational = lrng_sp80090b_startup_complete();
+		lrng_process_ready_list();
+		lrng_init_wakeup();
+	} else if (seed_bits >= LRNG_FULL_SEED_ENTROPY_BITS) {
+		invalidate_batched_entropy();
+		state->lrng_fully_seeded = true;
+		state->lrng_operational = lrng_sp80090b_startup_complete();
+		state->lrng_min_seeded = true;
+		pr_info("LRNG fully seeded with %u bits of entropy\n",
+			seed_bits);
+		lrng_set_entropy_thresh(LRNG_FULL_SEED_ENTROPY_BITS +
+					LRNG_CONDITIONING_ENTROPY_LOSS);
+		lrng_process_ready_list();
+		lrng_init_wakeup();
+
+	} else if (!state->lrng_min_seeded) {
+
+		/* DRNG is seeded with at least 128 bits of entropy */
+		if (seed_bits >= LRNG_MIN_SEED_ENTROPY_BITS) {
+			invalidate_batched_entropy();
+			state->lrng_min_seeded = true;
+			pr_info("LRNG minimally seeded with %u bits of entropy\n",
+				seed_bits);
+			lrng_set_entropy_thresh(
+				lrng_slow_noise_req_entropy(
+					LRNG_FULL_SEED_ENTROPY_BITS +
+					LRNG_CONDITIONING_ENTROPY_LOSS));
+			lrng_process_ready_list();
+			lrng_init_wakeup();
+
+		/* DRNG is seeded with at least LRNG_INIT_ENTROPY_BITS bits */
+		} else if (seed_bits >= LRNG_INIT_ENTROPY_BITS) {
+			pr_info("LRNG initial entropy level %u bits of entropy\n",
+				seed_bits);
+			lrng_set_entropy_thresh(
+				lrng_slow_noise_req_entropy(
+					LRNG_MIN_SEED_ENTROPY_BITS +
+					LRNG_CONDITIONING_ENTROPY_LOSS));
+		}
+	}
+}
+
+int __init rand_initialize(void)
+{
+	ktime_t now_time = ktime_get_real();
+	unsigned int i, rand;
+
+	lrng_pool_lfsr_u32(now_time);
+	for (i = 0; i < LRNG_POOL_SIZE; i++) {
+		if (!arch_get_random_seed_int(&rand) &&
+		    !arch_get_random_int(&rand))
+			rand = random_get_entropy();
+		lrng_pool_lfsr_u32(rand);
+	}
+	lrng_pool_lfsr_nonaligned((u8 *)utsname(), sizeof(*(utsname())));
+
+	return 0;
+}
diff --git a/drivers/char/lrng/lrng_sw_noise.c b/drivers/char/lrng/lrng_sw_noise.c
new file mode 100644
index 000000000000..c21db23875fc
--- /dev/null
+++ b/drivers/char/lrng/lrng_sw_noise.c
@@ -0,0 +1,102 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG Slow Noise Source: Interrupt data collection
+ *
+ * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#include <asm/irq_regs.h>
+#include <asm/ptrace.h>
+#include <linux/random.h>
+
+#include "lrng_internal.h"
+#include "lrng_sw_noise.h"
+
+/* Holder of time stamps before mixing them into the entropy pool */
+static DEFINE_PER_CPU(u32 [LRNG_TIME_ARRAY_SIZE], lrng_time);
+static DEFINE_PER_CPU(u32, lrng_time_ptr) = 0;
+static DEFINE_PER_CPU(u8, lrng_time_irqs) = 0;
+
+/*
+ * Batching up of entropy in per-CPU array before injecting into entropy pool.
+ */
+static inline void lrng_time_process(void)
+{
+	u32 i, ptr, now_time = random_get_entropy() &
+			       (likely(lrng_state_fully_seeded()) ?
+				LRNG_TIME_SLOTSIZE_MASK : (u32)-1);
+	enum lrng_health_res health_test;
+
+	/* Ensure sufficient space in lrng_time_irqs */
+	BUILD_BUG_ON(LRNG_TIME_NUM_VALUES >= (1 << (sizeof(u8) << 3)));
+	BUILD_BUG_ON(LRNG_TIME_ARRAY_MEMBER_BITS % LRNG_TIME_SLOTSIZE_BITS);
+	/* Ensure consistency of values */
+	BUILD_BUG_ON(LRNG_TIME_ARRAY_MEMBER_BITS != sizeof(lrng_time[0]) << 3);
+
+	if (lrng_raw_entropy_store(now_time))
+		return;
+
+	health_test = lrng_health_test(now_time);
+	if (health_test > lrng_health_fail_use)
+		return;
+
+	/* During boot time, we mix the full time stamp directly into LFSR */
+	if (unlikely(!lrng_state_fully_seeded())) {
+		lrng_pool_lfsr_u32(now_time);
+		if (health_test == lrng_health_pass)
+			lrng_pool_add_irq(1);
+		return;
+	}
+
+	ptr = this_cpu_inc_return(lrng_time_ptr) & LRNG_TIME_WORD_MASK;
+	this_cpu_or(lrng_time[lrng_time_idx2array(ptr)],
+		    lrng_time_slot_val(now_time & LRNG_TIME_SLOTSIZE_MASK,
+				       lrng_time_idx2slot(ptr)));
+
+	/* Interrupt delivers entropy if health test passes */
+	if (health_test == lrng_health_pass)
+		this_cpu_inc(lrng_time_irqs);
+
+	/* Only mix the buffer of time stamps into LFSR when wrapping */
+	if (ptr < LRNG_TIME_WORD_MASK)
+		return;
+
+	for (i = 0; i < LRNG_TIME_ARRAY_SIZE; i++) {
+		lrng_pool_lfsr_u32(this_cpu_read(lrng_time[i]));
+		this_cpu_write(lrng_time[i], 0);
+	}
+	lrng_pool_add_irq(this_cpu_read(lrng_time_irqs));
+	this_cpu_write(lrng_time_irqs, 0);
+}
+
+/*
+ * Hot code path - Callback for interrupt handler
+ */
+void add_interrupt_randomness(int irq, int irq_flags)
+{
+	lrng_time_process();
+
+	if (!lrng_pool_highres_timer()) {
+		struct pt_regs *regs = get_irq_regs();
+		static atomic_t reg_idx = ATOMIC_INIT(0);
+		u64 ip;
+
+		lrng_pool_lfsr_u32(jiffies);
+		lrng_pool_lfsr_u32(irq);
+		lrng_pool_lfsr_u32(irq_flags);
+
+		if (regs) {
+			u32 *ptr = (u32 *)regs;
+			int reg_ptr = atomic_add_return_relaxed(1, &reg_idx);
+			size_t n = (sizeof(struct pt_regs) / sizeof(u32));
+
+			ip = instruction_pointer(regs);
+			lrng_pool_lfsr_u32(*(ptr + (reg_ptr % n)));
+		} else
+			ip = _RET_IP_;
+
+		lrng_pool_lfsr_u32(ip >> 32);
+		lrng_pool_lfsr_u32(ip);
+	}
+}
+EXPORT_SYMBOL(add_interrupt_randomness);
diff --git a/drivers/char/lrng/lrng_sw_noise.h b/drivers/char/lrng/lrng_sw_noise.h
new file mode 100644
index 000000000000..107c6f9153bc
--- /dev/null
+++ b/drivers/char/lrng/lrng_sw_noise.h
@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
+/*
+ * LRNG Slow Noise Source: Time stamp array handling
+ *
+ * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+/*
+ * To limit the impact on the interrupt handling, the LRNG concatenates
+ * entropic LSB parts of the time stamps in a per-CPU array and only
+ * injects them into the entropy pool when the array is full.
+ */
+
+/* Store multiple integers in one u32 */
+#define LRNG_TIME_SLOTSIZE_BITS		(8)
+#define LRNG_TIME_SLOTSIZE_MASK		((1 << LRNG_TIME_SLOTSIZE_BITS) - 1)
+#define LRNG_TIME_ARRAY_MEMBER_BITS	(4 << 3)
+#define LRNG_TIME_SLOTS_PER_UINT	(LRNG_TIME_ARRAY_MEMBER_BITS / \
+					 LRNG_TIME_SLOTSIZE_BITS)
+
+/*
+ * Number of time values to store in the array - in small environments
+ * only one atomic_t variable per CPU is used.
+ */
+#define LRNG_TIME_NUM_VALUES		(CONFIG_BASE_SMALL ?		\
+					 LRNG_TIME_SLOTS_PER_UINT : 64)
+/* Mask of LSB of time stamp to store */
+#define LRNG_TIME_WORD_MASK		(LRNG_TIME_NUM_VALUES - 1)
+
+#define LRNG_TIME_SLOTS_MASK		(LRNG_TIME_SLOTS_PER_UINT - 1)
+#define LRNG_TIME_ARRAY_SIZE		(LRNG_TIME_NUM_VALUES /	\
+					 LRNG_TIME_SLOTS_PER_UINT)
+
+/* Starting bit index of slot */
+static inline unsigned int lrng_time_slot2bitindex(unsigned int slot)
+{
+	return (LRNG_TIME_SLOTSIZE_BITS * slot);
+}
+
+/* Convert index into the array index */
+static inline unsigned int lrng_time_idx2array(unsigned int idx)
+{
+	return idx / LRNG_TIME_SLOTS_PER_UINT;
+}
+
+/* Convert index into the slot of a given array index */
+static inline unsigned int lrng_time_idx2slot(unsigned int idx)
+{
+	return idx & LRNG_TIME_SLOTS_MASK;
+}
+
+/* Convert value into slot value */
+static inline unsigned int lrng_time_slot_val(unsigned int val,
+					      unsigned int slot)
+{
+	return val << lrng_time_slot2bitindex(slot);
+}
diff --git a/include/linux/lrng.h b/include/linux/lrng.h
new file mode 100644
index 000000000000..2c3d2ed32a91
--- /dev/null
+++ b/include/linux/lrng.h
@@ -0,0 +1,63 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
+/*
+ * Copyright (C) 2018 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#ifndef _LRNG_H
+#define _LRNG_H
+
+#include <linux/errno.h>
+#include <linux/types.h>
+
+/**
+ * struct lrng_crypto_cb - cryptographic callback functions
+ * @lrng_drng_name		Name of DRNG
+ * @lrng_hash_name		Name of Hash used for reading entropy pool
+ * @lrng_drng_alloc:		Allocate DRNG -- the provided integer should be
+ *				used for sanity checks.
+ *				return: allocated data structure or PTR_ERR on
+ *					error
+ * @lrng_drng_dealloc:		Deallocate DRNG
+ * @lrng_drng_seed_helper:	Seed the DRNG with data of arbitrary length
+ *				drng: is pointer to data structure allocated
+ *				      with lrng_drng_alloc
+ *				return: >= 0 on success, < 0 on error
+ * @lrng_drng_generate_helper:	Generate random numbers from the DRNG with
+ *				arbitrary length
+ * @lrng_hash_alloc:		Allocate the hash for reading the entropy pool
+ *				return: allocated data structure (NULL is
+ *					success too) or ERR_PTR on error
+ * @lrng_hash_dealloc:		Deallocate Hash
+ * @lrng_hash_digestsize:	Return the digestsize for the used hash to read
+ *				out entropy pool
+ *				hash: is pointer to data structure allocated
+ *				      with lrng_hash_alloc
+ *				return: size of digest of hash in bytes
+ * @lrng_hash_buffer:		Generate hash
+ *				hash: is pointer to data structure allocated
+ *				      with lrng_hash_alloc
+ *				return: 0 on success, < 0 on error
+ */
+struct lrng_crypto_cb {
+	const char *(*lrng_drng_name)(void);
+	const char *(*lrng_hash_name)(void);
+	void *(*lrng_drng_alloc)(u32 sec_strength);
+	void (*lrng_drng_dealloc)(void *drng);
+	int (*lrng_drng_seed_helper)(void *drng, const u8 *inbuf, u32 inbuflen);
+	int (*lrng_drng_generate_helper)(void *drng, u8 *outbuf, u32 outbuflen);
+	void *(*lrng_hash_alloc)(const u8 *key, u32 keylen);
+	void (*lrng_hash_dealloc)(void *hash);
+	u32 (*lrng_hash_digestsize)(void *hash);
+	int (*lrng_hash_buffer)(void *hash, const u8 *inbuf, u32 inbuflen,
+				u8 *digest);
+};
+
+/* Register cryptographic backend */
+#ifdef CONFIG_LRNG_DRNG_SWITCH
+int lrng_set_drng_cb(const struct lrng_crypto_cb *cb);
+#else	/* CONFIG_LRNG_DRNG_SWITCH */
+static inline int
+lrng_set_drng_cb(const struct lrng_crypto_cb *cb) { return -EOPNOTSUPP; }
+#endif	/* CONFIG_LRNG_DRNG_SWITCH */
+
+#endif /* _LRNG_H */
-- 
2.24.1





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v29 02/12] LRNG - allocate one DRNG instance per NUMA node
  2020-01-19 21:12         ` [PATCH v29 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
  2020-01-19 21:13           ` [PATCH v29 01/12] Linux Random Number Generator Stephan Müller
@ 2020-01-19 21:13           ` Stephan Müller
  2020-01-19 21:14           ` [PATCH v29 03/12] LRNG - sysctls and /proc interface Stephan Müller
                             ` (9 subsequent siblings)
  11 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2020-01-19 21:13 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap, Julia Lawall, Dan Carpenter

In order to improve NUMA-locality when serving getrandom(2) requests,
allocate one DRNG instance per node.

The DRNG instance that is present right from the start of the kernel is
reused as the first per-NUMA-node DRNG. For all remaining online NUMA
nodes a new DRNG instance is allocated.

During boot time, the multiple DRNG instances are seeded sequentially.
With this, the first DRNG instance (referenced as the initial DRNG
in the code) is completely seeded with 256 bits of entropy before the
next DRNG instance is completely seeded.

When random numbers are requested, the NUMA-node-local DRNG is checked
whether it has been already fully seeded. If this is not the case, the
initial DRNG is used to serve the request.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Makefile        |   2 +
 drivers/char/lrng/lrng_internal.h |   5 ++
 drivers/char/lrng/lrng_numa.c     | 101 ++++++++++++++++++++++++++++++
 3 files changed, 108 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_numa.c

diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index 1d2a0211973d..0a32f22c2c1a 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -7,3 +7,5 @@ obj-y				+= lrng_pool.o lrng_aux.o \
 				   lrng_sw_noise.o lrng_archrandom.o \
 				   lrng_drng.o lrng_chacha20.o \
 				   lrng_interfaces.o \
+
+obj-$(CONFIG_NUMA)		+= lrng_numa.o
diff --git a/drivers/char/lrng/lrng_internal.h b/drivers/char/lrng/lrng_internal.h
index edf38121ec65..ecb0a7ad5e7e 100644
--- a/drivers/char/lrng/lrng_internal.h
+++ b/drivers/char/lrng/lrng_internal.h
@@ -246,8 +246,13 @@ int lrng_drng_get_sleep(u8 *outbuf, u32 outbuflen);
 void lrng_drng_force_reseed(void);
 void lrng_drng_seed_work(struct work_struct *dummy);
 
+#ifdef CONFIG_NUMA
+struct lrng_drng **lrng_drng_instances(void);
+void lrng_drngs_numa_alloc(void);
+#else	/* CONFIG_NUMA */
 static inline struct lrng_drng **lrng_drng_instances(void) { return NULL; }
 static inline void lrng_drngs_numa_alloc(void) { return; }
+#endif /* CONFIG_NUMA */
 
 /************************** Health Test linking code **************************/
 
diff --git a/drivers/char/lrng/lrng_numa.c b/drivers/char/lrng/lrng_numa.c
new file mode 100644
index 000000000000..947c5b3ed517
--- /dev/null
+++ b/drivers/char/lrng/lrng_numa.c
@@ -0,0 +1,101 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG NUMA support
+ *
+ * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/lrng.h>
+#include <linux/slab.h>
+
+#include "lrng_internal.h"
+
+static struct lrng_drng **lrng_drng __read_mostly = NULL;
+
+struct lrng_drng **lrng_drng_instances(void)
+{
+	return lrng_drng;
+}
+
+/* Allocate the data structures for the per-NUMA node DRNGs */
+static void _lrng_drngs_numa_alloc(struct work_struct *work)
+{
+	struct lrng_drng **drngs;
+	struct lrng_drng *lrng_drng_init = lrng_drng_init_instance();
+	u32 node;
+	bool init_drng_used = false;
+
+	mutex_lock(&lrng_crypto_cb_update);
+
+	/* per-NUMA-node DRNGs are already present */
+	if (lrng_drng)
+		goto unlock;
+
+	drngs = kcalloc(nr_node_ids, sizeof(void *), GFP_KERNEL|__GFP_NOFAIL);
+	for_each_online_node(node) {
+		struct lrng_drng *drng;
+
+		if (!init_drng_used) {
+			drngs[node] = lrng_drng_init;
+			init_drng_used = true;
+			continue;
+		}
+
+		drng = kmalloc_node(sizeof(struct lrng_drng),
+				     GFP_KERNEL|__GFP_NOFAIL, node);
+		memset(drng, 0, sizeof(lrng_drng));
+
+		drng->crypto_cb = lrng_drng_init->crypto_cb;
+		drng->drng = drng->crypto_cb->lrng_drng_alloc(
+					LRNG_DRNG_SECURITY_STRENGTH_BYTES);
+		if (IS_ERR(drng->drng)) {
+			kfree(drng);
+			goto err;
+		}
+
+		mutex_init(&drng->lock);
+		spin_lock_init(&drng->spin_lock);
+
+		/*
+		 * No reseeding of NUMA DRNGs from previous DRNGs as this
+		 * would complicate the code. Let it simply reseed.
+		 */
+		lrng_drng_reset(drng);
+		drngs[node] = drng;
+
+		lrng_pool_inc_numa_node();
+		pr_info("DRNG for NUMA node %d allocated\n", node);
+	}
+
+	/* Ensure that all NUMA nodes receive changed memory here. */
+	mb();
+
+	if (!cmpxchg(&lrng_drng, NULL, drngs))
+		goto unlock;
+
+err:
+	for_each_online_node(node) {
+		struct lrng_drng *drng = drngs[node];
+
+		if (drng == lrng_drng_init)
+			continue;
+
+		if (drng) {
+			drng->crypto_cb->lrng_drng_dealloc(drng->drng);
+			kfree(drng);
+		}
+	}
+	kfree(drngs);
+
+unlock:
+	mutex_unlock(&lrng_crypto_cb_update);
+}
+
+static DECLARE_WORK(lrng_drngs_numa_alloc_work, _lrng_drngs_numa_alloc);
+
+void lrng_drngs_numa_alloc(void)
+{
+	schedule_work(&lrng_drngs_numa_alloc_work);
+}
-- 
2.24.1





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v29 03/12] LRNG - sysctls and /proc interface
  2020-01-19 21:12         ` [PATCH v29 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
  2020-01-19 21:13           ` [PATCH v29 01/12] Linux Random Number Generator Stephan Müller
  2020-01-19 21:13           ` [PATCH v29 02/12] LRNG - allocate one DRNG instance per NUMA node Stephan Müller
@ 2020-01-19 21:14           ` Stephan Müller
  2020-01-19 21:14           ` [PATCH v29 04/12] LRNG - add switchable DRNG support Stephan Müller
                             ` (8 subsequent siblings)
  11 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2020-01-19 21:14 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap, Julia Lawall, Dan Carpenter

The LRNG sysctl interface provides the same controls as the existing
/dev/random implementation. These sysctls behave identically and are
implemented identically. The goal is to allow a possible merge of the
existing /dev/random implementation with this implementation which
implies that this patch tries have a very close similarity. Yet, all
sysctls are documented at [1].

In addition, it provides the file lrng_type which provides details about
the LRNG:

- the name of the DRNG that produces the random numbers for /dev/random,
/dev/urandom, getrandom(2)

- the hash used to produce random numbers from the entropy pool

- the number of secondary DRNG instances

- indicator whether the LRNG operates SP800-90B compliant

- indicator whether a high-resolution timer is identified - only with a
high-resolution timer the interrupt noise source will deliver sufficient
entropy

- indicator whether the LRNG has been minimally seeded (i.e. is the
secondary DRNG seeded with at least 128 bits of of entropy)

- indicator whether the LRNG has been fully seeded (i.e. is the
secondary DRNG seeded with at least 256 bits of entropy)

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

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Makefile          |   1 +
 drivers/char/lrng/lrng_interfaces.c |   1 -
 drivers/char/lrng/lrng_internal.h   |   4 +
 drivers/char/lrng/lrng_proc.c       | 163 ++++++++++++++++++++++++++++
 4 files changed, 168 insertions(+), 1 deletion(-)
 create mode 100644 drivers/char/lrng/lrng_proc.c

diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index 0a32f22c2c1a..e69c176f0161 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -9,3 +9,4 @@ obj-y				+= lrng_pool.o lrng_aux.o \
 				   lrng_interfaces.o \
 
 obj-$(CONFIG_NUMA)		+= lrng_numa.o
+obj-$(CONFIG_SYSCTL)		+= lrng_proc.o
diff --git a/drivers/char/lrng/lrng_interfaces.c b/drivers/char/lrng/lrng_interfaces.c
index 6ad860866354..6ce5d0dfc34f 100644
--- a/drivers/char/lrng/lrng_interfaces.c
+++ b/drivers/char/lrng/lrng_interfaces.c
@@ -34,7 +34,6 @@ static DECLARE_WAIT_QUEUE_HEAD(lrng_write_wait);
 static DECLARE_WAIT_QUEUE_HEAD(lrng_init_wait);
 static struct fasync_struct *fasync;
 
-struct ctl_table random_table[];
 /********************************** Helper ***********************************/
 
 /* Is the DRNG seed level too low? */
diff --git a/drivers/char/lrng/lrng_internal.h b/drivers/char/lrng/lrng_internal.h
index ecb0a7ad5e7e..f65fc6647e8a 100644
--- a/drivers/char/lrng/lrng_internal.h
+++ b/drivers/char/lrng/lrng_internal.h
@@ -116,7 +116,11 @@ void lrng_cc20_init_state(struct chacha20_state *state);
 
 /********************************** /proc *************************************/
 
+#ifdef CONFIG_SYSCTL
+void lrng_pool_inc_numa_node(void);
+#else
 static inline void lrng_pool_inc_numa_node(void) { }
+#endif
 
 /****************************** LRNG interfaces *******************************/
 
diff --git a/drivers/char/lrng/lrng_proc.c b/drivers/char/lrng/lrng_proc.c
new file mode 100644
index 000000000000..f4ee01f61925
--- /dev/null
+++ b/drivers/char/lrng/lrng_proc.c
@@ -0,0 +1,163 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG proc and sysctl interfaces
+ *
+ * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#include <linux/lrng.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/sysctl.h>
+#include <linux/uuid.h>
+
+#include "lrng_internal.h"
+
+/*
+ * This function is used to return both the bootid UUID, and random
+ * UUID.  The difference is in whether table->data is NULL; if it is,
+ * then a new UUID is generated and returned to the user.
+ *
+ * If the user accesses this via the proc interface, the UUID will be
+ * returned as an ASCII string in the standard UUID format; if via the
+ * sysctl system call, as 16 bytes of binary data.
+ */
+static int lrng_proc_do_uuid(struct ctl_table *table, int write,
+			     void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	struct ctl_table fake_table;
+	unsigned char buf[64], tmp_uuid[16], *uuid;
+
+	uuid = table->data;
+	if (!uuid) {
+		uuid = tmp_uuid;
+		generate_random_uuid(uuid);
+	} else {
+		static DEFINE_SPINLOCK(bootid_spinlock);
+
+		spin_lock(&bootid_spinlock);
+		if (!uuid[8])
+			generate_random_uuid(uuid);
+		spin_unlock(&bootid_spinlock);
+	}
+
+	sprintf(buf, "%pU", uuid);
+
+	fake_table.data = buf;
+	fake_table.maxlen = sizeof(buf);
+
+	return proc_dostring(&fake_table, write, buffer, lenp, ppos);
+}
+
+static int lrng_proc_do_entropy(struct ctl_table *table, int write,
+				void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	struct ctl_table fake_table;
+	int entropy_count;
+
+	entropy_count = lrng_avail_entropy();
+
+	fake_table.data = &entropy_count;
+	fake_table.maxlen = sizeof(entropy_count);
+
+	return proc_dointvec(&fake_table, write, buffer, lenp, ppos);
+}
+
+static int lrng_sysctl_poolsize = LRNG_POOL_SIZE_BITS;
+static int lrng_min_write_thresh;
+static int lrng_max_write_thresh = LRNG_POOL_SIZE_BITS;
+static char lrng_sysctl_bootid[16];
+static int lrng_drng_reseed_max_min;
+
+struct ctl_table random_table[] = {
+	{
+		.procname	= "poolsize",
+		.data		= &lrng_sysctl_poolsize,
+		.maxlen		= sizeof(int),
+		.mode		= 0444,
+		.proc_handler	= proc_dointvec,
+	},
+	{
+		.procname	= "entropy_avail",
+		.maxlen		= sizeof(int),
+		.mode		= 0444,
+		.proc_handler	= lrng_proc_do_entropy,
+	},
+	{
+		.procname	= "write_wakeup_threshold",
+		.data		= &lrng_write_wakeup_bits,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec_minmax,
+		.extra1		= &lrng_min_write_thresh,
+		.extra2		= &lrng_max_write_thresh,
+	},
+	{
+		.procname	= "boot_id",
+		.data		= &lrng_sysctl_bootid,
+		.maxlen		= 16,
+		.mode		= 0444,
+		.proc_handler	= lrng_proc_do_uuid,
+	},
+	{
+		.procname	= "uuid",
+		.maxlen		= 16,
+		.mode		= 0444,
+		.proc_handler	= lrng_proc_do_uuid,
+	},
+	{
+		.procname       = "urandom_min_reseed_secs",
+		.data           = &lrng_drng_reseed_max_time,
+		.maxlen         = sizeof(int),
+		.mode           = 0644,
+		.proc_handler   = proc_dointvec,
+		.extra1		= &lrng_drng_reseed_max_min,
+	},
+	{ }
+};
+
+/* Number of online DRNGs */
+static u32 numa_drngs = 1;
+
+void lrng_pool_inc_numa_node(void)
+{
+	numa_drngs++;
+}
+
+static int lrng_proc_type_show(struct seq_file *m, void *v)
+{
+	struct lrng_drng *lrng_drng_init = lrng_drng_init_instance();
+	unsigned long flags = 0;
+	unsigned char buf[300];
+
+	lrng_drng_lock(lrng_drng_init, &flags);
+	snprintf(buf, sizeof(buf),
+		 "DRNG name: %s\n"
+		 "Hash for reading entropy pool: %s\n"
+		 "DRNG security strength: %d bits\n"
+		 "number of DRNG instances: %u\n"
+		 "SP800-90B compliance: %s\n"
+		 "High-resolution timer: %s\n"
+		 "LRNG minimally seeded: %s\n"
+		 "LRNG fully seeded: %s\n",
+		 lrng_drng_init->crypto_cb->lrng_drng_name(),
+		 lrng_drng_init->crypto_cb->lrng_hash_name(),
+		 LRNG_DRNG_SECURITY_STRENGTH_BITS, numa_drngs,
+		 lrng_sp80090b_compliant() ? "true" : "false",
+		 lrng_pool_highres_timer() ? "true" : "false",
+		 lrng_state_min_seeded() ? "true" : "false",
+		 lrng_state_fully_seeded() ? "true" : "false");
+	lrng_drng_unlock(lrng_drng_init, &flags);
+
+	seq_write(m, buf, strlen(buf));
+
+	return 0;
+}
+
+static int __init lrng_proc_type_init(void)
+{
+	proc_create_single("lrng_type", 0444, NULL, &lrng_proc_type_show);
+	return 0;
+}
+
+module_init(lrng_proc_type_init);
-- 
2.24.1





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v29 04/12] LRNG - add switchable DRNG support
  2020-01-19 21:12         ` [PATCH v29 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                             ` (2 preceding siblings ...)
  2020-01-19 21:14           ` [PATCH v29 03/12] LRNG - sysctls and /proc interface Stephan Müller
@ 2020-01-19 21:14           ` Stephan Müller
  2020-01-19 21:15           ` [PATCH v29 05/12] crypto: DRBG - externalize DRBG functions for LRNG Stephan Müller
                             ` (7 subsequent siblings)
  11 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2020-01-19 21:14 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap, Julia Lawall, Dan Carpenter

The DRNG switch support allows replacing the DRNG mechanism of the
LRNG. The switching support rests on the interface definition of
include/linux/lrng.h. A new DRNG is implemented by filling in the
interface defined in this header file.

In addition to the DRNG, the extension also has to provide a hash
implementation that is used to hash the entropy pool for random number
extraction.

Note: It is permissible to implement a DRNG whose operations may sleep.
However, the hash function must not sleep.

The switchable DRNG support allows replacing the DRNG at runtime.
However, only one DRNG extension is allowed to be loaded at any given
time. Before replacing it with another DRNG implementation, the possibly
existing DRNG extension must be unloaded.

The switchable DRNG extension activates the new DRNG during load time.
It is expected, however, that such a DRNG switch would be done only once
by an administrator to load the intended DRNG implementation.

It is permissible to compile DRNG extensions either as kernel modules or
statically. The initialization of the DRNG extension should be performed
with a late_initcall to ensure the extension is available when user
space starts but after all other initialization completed.
The initialization is performed by registering the function call data
structure with the lrng_set_drng_cb function. In order to unload the
DRNG extension, lrng_set_drng_cb must be invoked with the NULL
parameter.

The DRNG extension should always provide a security strength that is at
least as strong as LRNG_DRNG_SECURITY_STRENGTH_BITS.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Kconfig       |   7 ++
 drivers/char/lrng/Makefile      |   1 +
 drivers/char/lrng/lrng_switch.c | 182 ++++++++++++++++++++++++++++++++
 3 files changed, 190 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_switch.c

diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
index 56f13efd3592..cb701bb0b8b6 100644
--- a/drivers/char/lrng/Kconfig
+++ b/drivers/char/lrng/Kconfig
@@ -64,4 +64,11 @@ config LRNG_POOL_SIZE
 	default 7 if LRNG_POOL_SIZE_65536
 	default 8 if LRNG_POOL_SIZE_131072
 
+menuconfig LRNG_DRNG_SWITCH
+	bool "Support DRNG runtime switching"
+	help
+	  The Linux RNG per default uses a ChaCha20 DRNG that is
+	  accessible via the external interfaces. With this configuration
+	  option other DRNGs can be selected and loaded at runtime.
+
 endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index e69c176f0161..31cfe87c999e 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -10,3 +10,4 @@ obj-y				+= lrng_pool.o lrng_aux.o \
 
 obj-$(CONFIG_NUMA)		+= lrng_numa.o
 obj-$(CONFIG_SYSCTL)		+= lrng_proc.o
+obj-$(CONFIG_LRNG_DRNG_SWITCH)	+= lrng_switch.o
diff --git a/drivers/char/lrng/lrng_switch.c b/drivers/char/lrng/lrng_switch.c
new file mode 100644
index 000000000000..7101bda9d7aa
--- /dev/null
+++ b/drivers/char/lrng/lrng_switch.c
@@ -0,0 +1,182 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG DRNG switching support
+ *
+ * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/lrng.h>
+
+#include "lrng_internal.h"
+
+static int lrng_drng_switch(struct lrng_drng *drng_store,
+			    const struct lrng_crypto_cb *cb, int node)
+{
+	const struct lrng_crypto_cb *old_cb;
+	unsigned long flags = 0;
+	int ret;
+	u8 seed[LRNG_DRNG_SECURITY_STRENGTH_BYTES];
+	void *new_drng = cb->lrng_drng_alloc(LRNG_DRNG_SECURITY_STRENGTH_BYTES);
+	void *old_drng, *new_hash, *old_hash;
+	bool sl = false, reset_drng = !lrng_get_available();
+
+	if (IS_ERR(new_drng)) {
+		pr_warn("could not allocate new DRNG for NUMA node %d (%ld)\n",
+			node, PTR_ERR(new_drng));
+		return PTR_ERR(new_drng);
+	}
+
+	new_hash = cb->lrng_hash_alloc(seed, sizeof(seed));
+	if (IS_ERR(new_hash)) {
+		pr_warn("could not allocate new LRNG pool hash (%ld)\n",
+			PTR_ERR(new_hash));
+		cb->lrng_drng_dealloc(new_drng);
+		return PTR_ERR(new_hash);
+	}
+
+	lrng_drng_lock(drng_store, &flags);
+
+	/*
+	 * Pull from existing DRNG to seed new DRNG regardless of seed status
+	 * of old DRNG -- the entropy state for the DRNG is left unchanged which
+	 * implies that als the new DRNG is reseeded when deemed necessary. This
+	 * seeding of the new DRNG shall only ensure that the new DRNG has the
+	 * same entropy as the old DRNG.
+	 */
+	ret = drng_store->crypto_cb->lrng_drng_generate_helper(
+				drng_store->drng, seed, sizeof(seed));
+	lrng_drng_unlock(drng_store, &flags);
+
+	if (ret < 0) {
+		reset_drng = true;
+		pr_warn("getting random data from DRNG failed for NUMA node %d (%d)\n",
+			node, ret);
+	} else {
+		/* seed new DRNG with data */
+		ret = cb->lrng_drng_seed_helper(new_drng, seed, ret);
+		if (ret < 0) {
+			reset_drng = true;
+			pr_warn("seeding of new DRNG failed for NUMA node %d (%d)\n",
+				node, ret);
+		} else {
+			pr_debug("seeded new DRNG of NUMA node %d instance from old DRNG instance\n",
+				 node);
+		}
+	}
+
+	mutex_lock(&drng_store->lock);
+	/*
+	 * If we switch the DRNG from the initial ChaCha20 DRNG to something
+	 * else, there is a lock transition from spin lock to mutex (see
+	 * lrng_drng_is_atomic and how the lock is taken in lrng_drng_lock).
+	 * Thus, we need to take both locks during the transition phase.
+	 */
+	if (lrng_drng_is_atomic(drng_store)) {
+		spin_lock_irqsave(&drng_store->spin_lock, flags);
+		sl = true;
+	}
+
+	if (reset_drng)
+		lrng_drng_reset(drng_store);
+
+	old_drng = drng_store->drng;
+	old_cb = drng_store->crypto_cb;
+	drng_store->drng = new_drng;
+	drng_store->crypto_cb = cb;
+
+	old_hash = drng_store->hash;
+	drng_store->hash = new_hash;
+	pr_info("Entropy pool read-hash allocated for DRNG for NUMA node %d\n",
+		node);
+
+	if (sl)
+		spin_unlock_irqrestore(&drng_store->spin_lock, flags);
+	mutex_unlock(&drng_store->lock);
+
+	/* ChaCha20 serves as atomic instance left untouched. */
+	if (old_drng != &chacha20) {
+		old_cb->lrng_drng_dealloc(old_drng);
+		old_cb->lrng_hash_dealloc(old_hash);
+	}
+
+	pr_info("DRNG of NUMA node %d switched\n", node);
+
+	return 0;
+}
+
+/*
+ * Switch the existing DRNG instances with new using the new crypto callbacks.
+ * The caller must hold the lrng_crypto_cb_update lock.
+ */
+static int lrng_drngs_switch(const struct lrng_crypto_cb *cb)
+{
+	struct lrng_drng **lrng_drng = lrng_drng_instances();
+	struct lrng_drng *lrng_drng_init = lrng_drng_init_instance();
+	int ret = 0;
+
+	/* Update DRNG */
+	if (lrng_drng) {
+		u32 node;
+
+		for_each_online_node(node) {
+			if (lrng_drng[node])
+				ret = lrng_drng_switch(lrng_drng[node], cb,
+						       node);
+		}
+	} else {
+		ret = lrng_drng_switch(lrng_drng_init, cb, 0);
+	}
+
+	if (!ret)
+		lrng_set_available();
+
+	return 0;
+}
+
+/**
+ * lrng_set_drng_cb - Register new cryptographic callback functions for DRNG
+ * The registering implies that all old DRNG states are replaced with new
+ * DRNG states.
+ *
+ * @cb: Callback functions to be registered -- if NULL, use the default
+ *	callbacks pointing to the ChaCha20 DRNG.
+ *
+ * Return:
+ * * 0 on success
+ * * < 0 on error
+ */
+int lrng_set_drng_cb(const struct lrng_crypto_cb *cb)
+{
+	struct lrng_drng *lrng_drng_init = lrng_drng_init_instance();
+	int ret;
+
+	if (!cb)
+		cb = &lrng_cc20_crypto_cb;
+
+	mutex_lock(&lrng_crypto_cb_update);
+
+	/*
+	 * If a callback other than the default is set, allow it only to be
+	 * set back to the default callback. This ensures that multiple
+	 * different callbacks can be registered at the same time. If a
+	 * callback different from the current callback and the default
+	 * callback shall be set, the current callback must be deregistered
+	 * (e.g. the kernel module providing it must be unloaded) and the new
+	 * implementation can be registered.
+	 */
+	if ((cb != &lrng_cc20_crypto_cb) &&
+	    (lrng_drng_init->crypto_cb != &lrng_cc20_crypto_cb)) {
+		pr_warn("disallow setting new cipher callbacks, unload the old callbacks first!\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	ret = lrng_drngs_switch(cb);
+
+out:
+	mutex_unlock(&lrng_crypto_cb_update);
+	return ret;
+}
+EXPORT_SYMBOL(lrng_set_drng_cb);
-- 
2.24.1





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v29 05/12] crypto: DRBG - externalize DRBG functions for LRNG
  2020-01-19 21:12         ` [PATCH v29 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                             ` (3 preceding siblings ...)
  2020-01-19 21:14           ` [PATCH v29 04/12] LRNG - add switchable DRNG support Stephan Müller
@ 2020-01-19 21:15           ` Stephan Müller
  2020-01-19 21:16           ` [PATCH v29 06/12] LRNG - add SP800-90A DRBG extension Stephan Müller
                             ` (6 subsequent siblings)
  11 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2020-01-19 21:15 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap, Julia Lawall, Dan Carpenter

This patch allows several DRBG functions to be called by the LRNG kernel
code paths outside the drbg.c file.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 crypto/drbg.c         | 16 ++++++++++------
 include/crypto/drbg.h |  7 +++++++
 2 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/crypto/drbg.c b/crypto/drbg.c
index b6929eb5f565..5561dd0f09e1 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -113,7 +113,7 @@
  * the SHA256 / AES 256 over other ciphers. Thus, the favored
  * DRBGs are the latest entries in this array.
  */
-static const struct drbg_core drbg_cores[] = {
+const struct drbg_core drbg_cores[] = {
 #ifdef CONFIG_CRYPTO_DRBG_CTR
 	{
 		.flags = DRBG_CTR | DRBG_STRENGTH128,
@@ -190,6 +190,7 @@ static const struct drbg_core drbg_cores[] = {
 	},
 #endif /* CONFIG_CRYPTO_DRBG_HMAC */
 };
+EXPORT_SYMBOL(drbg_cores);
 
 static int drbg_uninstantiate(struct drbg_state *drbg);
 
@@ -205,7 +206,7 @@ static int drbg_uninstantiate(struct drbg_state *drbg);
  * Return: normalized strength in *bytes* value or 32 as default
  *	   to counter programming errors
  */
-static inline unsigned short drbg_sec_strength(drbg_flag_t flags)
+unsigned short drbg_sec_strength(drbg_flag_t flags)
 {
 	switch (flags & DRBG_STRENGTH_MASK) {
 	case DRBG_STRENGTH128:
@@ -218,6 +219,7 @@ static inline unsigned short drbg_sec_strength(drbg_flag_t flags)
 		return 32;
 	}
 }
+EXPORT_SYMBOL(drbg_sec_strength);
 
 /*
  * FIPS 140-2 continuous self test for the noise source
@@ -1202,7 +1204,7 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
 }
 
 /* Free all substructures in a DRBG state without the DRBG state structure */
-static inline void drbg_dealloc_state(struct drbg_state *drbg)
+void drbg_dealloc_state(struct drbg_state *drbg)
 {
 	if (!drbg)
 		return;
@@ -1223,12 +1225,13 @@ static inline void drbg_dealloc_state(struct drbg_state *drbg)
 		drbg->fips_primed = false;
 	}
 }
+EXPORT_SYMBOL(drbg_dealloc_state);
 
 /*
  * Allocate all sub-structures for a DRBG state.
  * The DRBG state structure must already be allocated.
  */
-static inline int drbg_alloc_state(struct drbg_state *drbg)
+int drbg_alloc_state(struct drbg_state *drbg)
 {
 	int ret = -ENOMEM;
 	unsigned int sb_size = 0;
@@ -1307,6 +1310,7 @@ static inline int drbg_alloc_state(struct drbg_state *drbg)
 	drbg_dealloc_state(drbg);
 	return ret;
 }
+EXPORT_SYMBOL(drbg_alloc_state);
 
 /*************************************************************************
  * DRBG interface functions
@@ -1874,8 +1878,7 @@ static int drbg_kcapi_sym_ctr(struct drbg_state *drbg,
  *
  * return: flags
  */
-static inline void drbg_convert_tfm_core(const char *cra_driver_name,
-					 int *coreref, bool *pr)
+void drbg_convert_tfm_core(const char *cra_driver_name, int *coreref, bool *pr)
 {
 	int i = 0;
 	size_t start = 0;
@@ -1902,6 +1905,7 @@ static inline void drbg_convert_tfm_core(const char *cra_driver_name,
 		}
 	}
 }
+EXPORT_SYMBOL(drbg_convert_tfm_core);
 
 static int drbg_kcapi_init(struct crypto_tfm *tfm)
 {
diff --git a/include/crypto/drbg.h b/include/crypto/drbg.h
index 8c9af21efce1..c63b20375235 100644
--- a/include/crypto/drbg.h
+++ b/include/crypto/drbg.h
@@ -282,4 +282,11 @@ enum drbg_prefixes {
 	DRBG_PREFIX3
 };
 
+extern int drbg_alloc_state(struct drbg_state *drbg);
+extern void drbg_dealloc_state(struct drbg_state *drbg);
+extern void drbg_convert_tfm_core(const char *cra_driver_name, int *coreref,
+				  bool *pr);
+extern const struct drbg_core drbg_cores[];
+extern unsigned short drbg_sec_strength(drbg_flag_t flags);
+
 #endif /* _DRBG_H */
-- 
2.24.1





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v29 06/12] LRNG - add SP800-90A DRBG extension
  2020-01-19 21:12         ` [PATCH v29 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                             ` (4 preceding siblings ...)
  2020-01-19 21:15           ` [PATCH v29 05/12] crypto: DRBG - externalize DRBG functions for LRNG Stephan Müller
@ 2020-01-19 21:16           ` Stephan Müller
  2020-01-19 21:16           ` [PATCH v29 07/12] LRNG - add kernel crypto API PRNG extension Stephan Müller
                             ` (5 subsequent siblings)
  11 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2020-01-19 21:16 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap, Julia Lawall, Dan Carpenter

Using the LRNG switchable DRNG support, the SP800-90A DRBG extension is
implemented.

The DRBG uses the kernel crypto API DRBG implementation. In addition, it
uses the kernel crypto API SHASH support to provide the hashing
operation.

The DRBG supports the choice of either a CTR DRBG using AES-256, HMAC
DRBG with SHA-512 core or Hash DRBG with SHA-512 core. The used core can
be selected with the module parameter lrng_drbg_type. The default is the
CTR DRBG.

When compiling the DRBG extension statically, the DRBG is loaded at
late_initcall stage which implies that with the start of user space, the
user space interfaces of getrandom(2), /dev/random and /dev/urandom
provide random data produced by an SP800-90A DRBG.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Kconfig     |  12 ++
 drivers/char/lrng/Makefile    |   1 +
 drivers/char/lrng/lrng_drbg.c | 257 ++++++++++++++++++++++++++++++++++
 3 files changed, 270 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_drbg.c

diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
index cb701bb0b8b6..b32442484823 100644
--- a/drivers/char/lrng/Kconfig
+++ b/drivers/char/lrng/Kconfig
@@ -71,4 +71,16 @@ menuconfig LRNG_DRNG_SWITCH
 	  accessible via the external interfaces. With this configuration
 	  option other DRNGs can be selected and loaded at runtime.
 
+if LRNG_DRNG_SWITCH
+config LRNG_DRBG
+	tristate "SP800-90A support for the LRNG"
+	depends on CRYPTO
+	select CRYPTO_DRBG_MENU
+	select CRYPTO_CMAC if CRYPTO_DRBG_CTR
+	help
+	  Enable the SP800-90A DRBG support for the LRNG. Once the
+	  module is loaded, output from /dev/random, /dev/urandom,
+	  getrandom(2), or get_random_bytes is provided by a DRBG.
+endif # LRNG_DRNG_SWITCH
+
 endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index 31cfe87c999e..0d320fcb7b9e 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -11,3 +11,4 @@ obj-y				+= lrng_pool.o lrng_aux.o \
 obj-$(CONFIG_NUMA)		+= lrng_numa.o
 obj-$(CONFIG_SYSCTL)		+= lrng_proc.o
 obj-$(CONFIG_LRNG_DRNG_SWITCH)	+= lrng_switch.o
+obj-$(CONFIG_LRNG_DRBG)		+= lrng_drbg.o
diff --git a/drivers/char/lrng/lrng_drbg.c b/drivers/char/lrng/lrng_drbg.c
new file mode 100644
index 000000000000..f35e7b886d01
--- /dev/null
+++ b/drivers/char/lrng/lrng_drbg.c
@@ -0,0 +1,257 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * Backend for the LRNG providing the cryptographic primitives using the
+ * kernel crypto API and its DRBG.
+ *
+ * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <crypto/drbg.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/lrng.h>
+
+/*
+ * Define a DRBG plus a hash / MAC used to extract data from the entropy pool.
+ * For LRNG_HASH_NAME you can use a hash or a MAC (HMAC or CMAC) of your choice
+ * (Note, you should use the suggested selections below -- using SHA-1 or MD5
+ * is not wise). The idea is that the used cipher primitive can be selected to
+ * be the same as used for the DRBG. I.e. the LRNG only uses one cipher
+ * primitive using the same cipher implementation with the options offered in
+ * the following. This means, if the CTR DRBG is selected and AES-NI is present,
+ * both the CTR DRBG and the selected cmac(aes) use AES-NI.
+ *
+ * The security strengths of the DRBGs are all 256 bits according to
+ * SP800-57 section 5.6.1.
+ *
+ * This definition is allowed to be changed.
+ */
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+static unsigned int lrng_drbg_type = 0;
+#elif defined CONFIG_CRYPTO_DRBG_HMAC
+static unsigned int lrng_drbg_type = 1;
+#elif defined CONFIG_CRYPTO_DRBG_HASH
+static unsigned int lrng_drbg_type = 2;
+#else
+#error "Unknown DRBG in use"
+#endif
+
+/* The parameter must be r/o in sysfs as otherwise races appear. */
+module_param(lrng_drbg_type, uint, 0444);
+MODULE_PARM_DESC(lrng_drbg_type, "DRBG type used for LRNG (0->CTR_DRBG, 1->HMAC_DRBG, 2->Hash_DRBG)");
+
+struct lrng_drbg {
+	const char *hash_name;
+	const char *drbg_core;
+};
+
+static const struct lrng_drbg lrng_drbg_types[] = {
+	{	/* CTR_DRBG with AES-256 using derivation function */
+		.hash_name = "cmac(aes)",
+		.drbg_core = "drbg_nopr_ctr_aes256",
+	}, {	/* HMAC_DRBG with SHA-512 */
+		.hash_name = "sha512",
+		.drbg_core = "drbg_nopr_hmac_sha512",
+	}, {	/* Hash_DRBG with SHA-512 using derivation function */
+		.hash_name = "sha512",
+		.drbg_core = "drbg_nopr_sha512"
+	}
+};
+
+struct lrng_hash_info {
+	struct shash_desc shash;
+	char ctx[];
+};
+
+static int lrng_drbg_drng_seed_helper(void *drng, const u8 *inbuf, u32 inbuflen)
+{
+	struct drbg_state *drbg = (struct drbg_state *)drng;
+	LIST_HEAD(seedlist);
+	struct drbg_string data;
+	int ret;
+
+	drbg_string_fill(&data, inbuf, inbuflen);
+	list_add_tail(&data.list, &seedlist);
+	ret = drbg->d_ops->update(drbg, &seedlist, drbg->seeded);
+
+	if (ret >= 0)
+		drbg->seeded = true;
+
+	return ret;
+}
+
+static int lrng_drbg_drng_generate_helper(void *drng, u8 *outbuf, u32 outbuflen)
+{
+	struct drbg_state *drbg = (struct drbg_state *)drng;
+
+	return drbg->d_ops->generate(drbg, outbuf, outbuflen, NULL);
+}
+
+static void *lrng_drbg_drng_alloc(u32 sec_strength)
+{
+	struct drbg_state *drbg;
+	int coreref = -1;
+	bool pr = false;
+	int ret;
+
+	drbg_convert_tfm_core(lrng_drbg_types[lrng_drbg_type].drbg_core,
+			      &coreref, &pr);
+	if (coreref < 0)
+		return ERR_PTR(-EFAULT);
+
+	drbg = kzalloc(sizeof(struct drbg_state), GFP_KERNEL);
+	if (!drbg)
+		return ERR_PTR(-ENOMEM);
+
+	drbg->core = &drbg_cores[coreref];
+	drbg->seeded = false;
+	ret = drbg_alloc_state(drbg);
+	if (ret)
+		goto err;
+
+	if (sec_strength > drbg_sec_strength(drbg->core->flags)) {
+		pr_err("Security strength of DRBG (%u bits) lower than requested by LRNG (%u bits)\n",
+			drbg_sec_strength(drbg->core->flags) * 8,
+			sec_strength * 8);
+		goto dealloc;
+	}
+
+	if (sec_strength < drbg_sec_strength(drbg->core->flags))
+		pr_warn("Security strength of DRBG (%u bits) higher than requested by LRNG (%u bits)\n",
+			drbg_sec_strength(drbg->core->flags) * 8,
+			sec_strength * 8);
+
+	pr_info("DRBG with %s core allocated\n", drbg->core->backend_cra_name);
+
+	return drbg;
+
+dealloc:
+	if (drbg->d_ops)
+		drbg->d_ops->crypto_fini(drbg);
+	drbg_dealloc_state(drbg);
+err:
+	kfree(drbg);
+	return ERR_PTR(-EINVAL);
+}
+
+static void lrng_drbg_drng_dealloc(void *drng)
+{
+	struct drbg_state *drbg = (struct drbg_state *)drng;
+
+	drbg_dealloc_state(drbg);
+	kzfree(drbg);
+	pr_info("DRBG deallocated\n");
+}
+
+static void *lrng_drbg_hash_alloc(const u8 *key, u32 keylen)
+{
+	struct lrng_hash_info *lrng_hash;
+	struct crypto_shash *tfm;
+	int size, ret;
+
+	tfm = crypto_alloc_shash(lrng_drbg_types[lrng_drbg_type].hash_name,
+				 0, 0);
+	if (IS_ERR(tfm)) {
+		pr_err("could not allocate hash %s\n",
+		       lrng_drbg_types[lrng_drbg_type].hash_name);
+		return ERR_CAST(tfm);
+	}
+
+	size = sizeof(struct lrng_hash_info) + crypto_shash_descsize(tfm);
+	lrng_hash = kmalloc(size, GFP_KERNEL);
+	if (!lrng_hash) {
+		crypto_free_shash(tfm);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	lrng_hash->shash.tfm = tfm;
+
+	/* If the used hash is no MAC, ignore the ENOSYS return code */
+	ret = crypto_shash_setkey(tfm, key, keylen);
+	if (ret && ret != -ENOSYS) {
+		pr_err("could not set the key for MAC\n");
+		crypto_free_shash(tfm);
+		kfree(lrng_hash);
+		return ERR_PTR(ret);
+	}
+
+	pr_info("Hash %s allocated\n",
+		lrng_drbg_types[lrng_drbg_type].hash_name);
+
+	return lrng_hash;
+}
+
+static void lrng_drbg_hash_dealloc(void *hash)
+{
+	struct lrng_hash_info *lrng_hash = (struct lrng_hash_info *)hash;
+	struct shash_desc *shash = &lrng_hash->shash;
+	struct crypto_shash *tfm = shash->tfm;
+
+	crypto_free_shash(tfm);
+	kfree(lrng_hash);
+	pr_info("Hash deallocated\n");
+}
+
+static u32 lrng_drbg_hash_digestsize(void *hash)
+{
+	struct lrng_hash_info *lrng_hash = (struct lrng_hash_info *)hash;
+	struct shash_desc *shash = &lrng_hash->shash;
+
+	return crypto_shash_digestsize(shash->tfm);
+}
+
+static int lrng_drbg_hash_buffer(void *hash, const u8 *inbuf, u32 inbuflen,
+				 u8 *digest)
+{
+	struct lrng_hash_info *lrng_hash = (struct lrng_hash_info *)hash;
+	struct shash_desc *shash = &lrng_hash->shash;
+
+	return crypto_shash_digest(shash, inbuf, inbuflen, digest);
+}
+
+static const char *lrng_drbg_name(void)
+{
+	return lrng_drbg_types[lrng_drbg_type].drbg_core;
+}
+
+static const char *lrng_hash_name(void)
+{
+	return lrng_drbg_types[lrng_drbg_type].hash_name;
+}
+
+const static struct lrng_crypto_cb lrng_drbg_crypto_cb = {
+	.lrng_drng_name			= lrng_drbg_name,
+	.lrng_hash_name			= lrng_hash_name,
+	.lrng_drng_alloc		= lrng_drbg_drng_alloc,
+	.lrng_drng_dealloc		= lrng_drbg_drng_dealloc,
+	.lrng_drng_seed_helper		= lrng_drbg_drng_seed_helper,
+	.lrng_drng_generate_helper	= lrng_drbg_drng_generate_helper,
+	.lrng_hash_alloc		= lrng_drbg_hash_alloc,
+	.lrng_hash_dealloc		= lrng_drbg_hash_dealloc,
+	.lrng_hash_digestsize		= lrng_drbg_hash_digestsize,
+	.lrng_hash_buffer		= lrng_drbg_hash_buffer,
+};
+
+static int __init lrng_drbg_init(void)
+{
+	if (lrng_drbg_type >= ARRAY_SIZE(lrng_drbg_types)) {
+		pr_err("lrng_drbg_type parameter too large (given %u - max: %lu)",
+		       lrng_drbg_type,
+		       (unsigned long)ARRAY_SIZE(lrng_drbg_types) - 1);
+		return -EAGAIN;
+	}
+	return lrng_set_drng_cb(&lrng_drbg_crypto_cb);
+}
+
+static void __exit lrng_drbg_exit(void)
+{
+	lrng_set_drng_cb(NULL);
+}
+
+late_initcall(lrng_drbg_init);
+module_exit(lrng_drbg_exit);
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
+MODULE_DESCRIPTION("Linux Random Number Generator - SP800-90A DRBG backend");
-- 
2.24.1





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v29 07/12] LRNG - add kernel crypto API PRNG extension
  2020-01-19 21:12         ` [PATCH v29 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                             ` (5 preceding siblings ...)
  2020-01-19 21:16           ` [PATCH v29 06/12] LRNG - add SP800-90A DRBG extension Stephan Müller
@ 2020-01-19 21:16           ` Stephan Müller
  2020-01-19 21:17           ` [PATCH v29 08/12] crypto: provide access to a static Jitter RNG state Stephan Müller
                             ` (4 subsequent siblings)
  11 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2020-01-19 21:16 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap, Julia Lawall, Dan Carpenter

Add runtime-pluggable support for all PRNGs that are accessible via
the kernel crypto API, including hardware PRNGs. The PRNG is selected
with the module parameter drng_name where the name must be one that the
kernel crypto API can resolve into an RNG.

This allows using of the kernel crypto API PRNG implementations that
provide an interface to hardware PRNGs. Using this extension,
the LRNG uses the hardware PRNGs to generate random numbers. An
example is the S390 CPACF support providing such a PRNG.

The hash is provided by a kernel crypto API SHASH whose digest size
complies with the seedsize of the PRNG.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Kconfig      |  11 ++
 drivers/char/lrng/Makefile     |   1 +
 drivers/char/lrng/lrng_kcapi.c | 321 +++++++++++++++++++++++++++++++++
 3 files changed, 333 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_kcapi.c

diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
index b32442484823..7afc965a4d52 100644
--- a/drivers/char/lrng/Kconfig
+++ b/drivers/char/lrng/Kconfig
@@ -81,6 +81,17 @@ config LRNG_DRBG
 	  Enable the SP800-90A DRBG support for the LRNG. Once the
 	  module is loaded, output from /dev/random, /dev/urandom,
 	  getrandom(2), or get_random_bytes is provided by a DRBG.
+
+config LRNG_KCAPI
+	tristate "Kernel Crypto API support for the LRNG"
+	depends on CRYPTO
+	select CRYPTO_RNG
+	help
+	  Enable the support for generic pseudo-random number
+	  generators offered by the kernel crypto API with the
+	  LRNG. Once the module is loaded, output from /dev/random,
+	  /dev/urandom, getrandom(2), or get_random_bytes is
+	  provided by the selected kernel crypto API RNG.
 endif # LRNG_DRNG_SWITCH
 
 endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index 0d320fcb7b9e..94b2dfb2dfdb 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -12,3 +12,4 @@ obj-$(CONFIG_NUMA)		+= lrng_numa.o
 obj-$(CONFIG_SYSCTL)		+= lrng_proc.o
 obj-$(CONFIG_LRNG_DRNG_SWITCH)	+= lrng_switch.o
 obj-$(CONFIG_LRNG_DRBG)		+= lrng_drbg.o
+obj-$(CONFIG_LRNG_KCAPI)	+= lrng_kcapi.o
diff --git a/drivers/char/lrng/lrng_kcapi.c b/drivers/char/lrng/lrng_kcapi.c
new file mode 100644
index 000000000000..482f31627422
--- /dev/null
+++ b/drivers/char/lrng/lrng_kcapi.c
@@ -0,0 +1,321 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * Backend for the LRNG providing the cryptographic primitives using the
+ * kernel crypto API.
+ *
+ * Copyright (C) 2018 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <crypto/hash.h>
+#include <crypto/rng.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/lrng.h>
+
+static char *drng_name = NULL;
+module_param(drng_name, charp, 0444);
+MODULE_PARM_DESC(drng_name, "Kernel crypto API name of DRNG");
+
+static char *pool_hash = "sha512";
+module_param(pool_hash, charp, 0444);
+MODULE_PARM_DESC(pool_hash,
+		 "Kernel crypto API name of hash or keyed message digest to read the entropy pool");
+
+static char *seed_hash = NULL;
+module_param(seed_hash, charp, 0444);
+MODULE_PARM_DESC(seed_hash,
+		 "Kernel crypto API name of hash with output size equal to seedsize of DRNG to bring seed string to the size required by the DRNG");
+
+struct lrng_hash_info {
+	struct shash_desc shash;
+	char ctx[];
+};
+
+struct lrng_drng_info {
+	struct crypto_rng *kcapi_rng;
+	struct lrng_hash_info *lrng_hash;
+};
+
+static struct lrng_hash_info *_lrng_kcapi_hash_alloc(const char *name)
+{
+	struct lrng_hash_info *lrng_hash;
+	struct crypto_shash *tfm;
+	int size;
+
+	if (!name) {
+		pr_err("Hash name missing\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	tfm = crypto_alloc_shash(name, 0, 0);
+	if (IS_ERR(tfm)) {
+		pr_err("could not allocate hash %s\n", name);
+		return ERR_CAST(tfm);
+	}
+
+	size = sizeof(struct lrng_hash_info) + crypto_shash_descsize(tfm);
+	lrng_hash = kmalloc(size, GFP_KERNEL);
+	if (!lrng_hash) {
+		crypto_free_shash(tfm);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	lrng_hash->shash.tfm = tfm;
+
+	return lrng_hash;
+}
+
+static inline u32 _lrng_kcapi_hash_digestsize(struct lrng_hash_info *lrng_hash)
+{
+	struct shash_desc *shash = &lrng_hash->shash;
+	struct crypto_shash *tfm = shash->tfm;
+
+	return crypto_shash_digestsize(tfm);
+}
+
+static inline void _lrng_kcapi_hash_free(struct lrng_hash_info *lrng_hash)
+{
+	struct shash_desc *shash = &lrng_hash->shash;
+	struct crypto_shash *tfm = shash->tfm;
+
+	crypto_free_shash(tfm);
+	kfree(lrng_hash);
+}
+
+static void *lrng_kcapi_hash_alloc(const u8 *key, u32 keylen)
+{
+	struct lrng_hash_info *lrng_hash;
+	int ret;
+
+	lrng_hash = _lrng_kcapi_hash_alloc(pool_hash);
+	if (IS_ERR(lrng_hash))
+		return ERR_CAST(lrng_hash);
+
+	/* If the used hash is no MAC, ignore the ENOSYS return code */
+	ret = crypto_shash_setkey(lrng_hash->shash.tfm, key, keylen);
+	if (ret && ret != -ENOSYS) {
+		pr_err("could not set the key for MAC\n");
+		_lrng_kcapi_hash_free(lrng_hash);
+		return ERR_PTR(ret);
+	}
+
+	pr_info("Hash %s allocated\n", pool_hash);
+
+	return lrng_hash;
+}
+
+static void lrng_kcapi_hash_dealloc(void *hash)
+{
+	struct lrng_hash_info *lrng_hash = (struct lrng_hash_info *)hash;
+
+	_lrng_kcapi_hash_free(lrng_hash);
+	pr_info("Hash %s deallocated\n", pool_hash);
+}
+
+static u32 lrng_kcapi_hash_digestsize(void *hash)
+{
+	struct lrng_hash_info *lrng_hash = (struct lrng_hash_info *)hash;
+
+	return _lrng_kcapi_hash_digestsize(lrng_hash);
+}
+
+static int lrng_kcapi_hash_buffer(void *hash, const u8 *inbuf, u32 inbuflen,
+				  u8 *digest)
+{
+	struct lrng_hash_info *lrng_hash = (struct lrng_hash_info *)hash;
+	struct shash_desc *shash = &lrng_hash->shash;
+
+	return crypto_shash_digest(shash, inbuf, inbuflen, digest);
+}
+
+static int lrng_kcapi_drng_seed_helper(void *drng, const u8 *inbuf,
+				       u32 inbuflen)
+{
+	struct lrng_drng_info *lrng_drng_info = (struct lrng_drng_info *)drng;
+	struct crypto_rng *kcapi_rng = lrng_drng_info->kcapi_rng;
+	struct lrng_hash_info *lrng_hash = lrng_drng_info->lrng_hash;
+
+	if (lrng_hash) {
+		struct shash_desc *shash = &lrng_hash->shash;
+		u32 digestsize = _lrng_kcapi_hash_digestsize(lrng_hash);
+		u8 digest[64] __aligned(8);
+		int ret;
+
+		BUG_ON(digestsize > sizeof(digest));
+
+		ret = crypto_shash_digest(shash, inbuf, inbuflen, digest);
+		if (ret)
+			return ret;
+
+		ret = crypto_rng_reset(kcapi_rng, digest, digestsize);
+		if (ret)
+			return ret;
+
+		memzero_explicit(digest, digestsize);
+
+		return 0;
+	} else {
+		return crypto_rng_reset(kcapi_rng, inbuf, inbuflen);
+	}
+}
+
+static int lrng_kcapi_drng_generate_helper(void *drng, u8 *outbuf,
+					   u32 outbuflen)
+{
+	struct lrng_drng_info *lrng_drng_info = (struct lrng_drng_info *)drng;
+	struct crypto_rng *kcapi_rng = lrng_drng_info->kcapi_rng;
+	int ret = crypto_rng_get_bytes(kcapi_rng, outbuf, outbuflen);
+
+	if (ret < 0)
+		return ret;
+
+	return outbuflen;
+}
+
+static void *lrng_kcapi_drng_alloc(u32 sec_strength)
+{
+	struct lrng_drng_info *lrng_drng_info;
+	struct crypto_rng *kcapi_rng;
+	int seedsize;
+	void *ret =  ERR_PTR(-ENOMEM);
+
+	if (!drng_name) {
+		pr_err("DRNG name missing\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (!memcmp(drng_name, "drbg", 4)) {
+		pr_err("SP800-90A DRBG cannot be allocated using lrng_kcapi backend, use lrng_drbg backend instead\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (!memcmp(drng_name, "stdrng", 6)) {
+		pr_err("stdrng cannot be allocated using lrng_kcapi backend, it is too unspecific and potentially may allocate the DRBG\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	lrng_drng_info = kmalloc(sizeof(*lrng_drng_info), GFP_KERNEL);
+	if (!lrng_drng_info)
+		return ERR_PTR(-ENOMEM);
+
+	kcapi_rng = crypto_alloc_rng(drng_name, 0, 0);
+	if (IS_ERR(kcapi_rng)) {
+		pr_err("DRNG %s cannot be allocated\n", drng_name);
+		ret = ERR_CAST(kcapi_rng);
+		goto free;
+	}
+	lrng_drng_info->kcapi_rng = kcapi_rng;
+
+	seedsize =  crypto_rng_seedsize(kcapi_rng);
+
+	if (sec_strength > seedsize)
+		pr_info("Seedsize DRNG (%u bits) lower than security strength of LRNG noise source (%u bits)\n",
+			crypto_rng_seedsize(kcapi_rng) * 8, sec_strength * 8);
+
+	if (seedsize) {
+		struct lrng_hash_info *lrng_hash;
+
+		if (!seed_hash) {
+			switch (seedsize) {
+			case 32:
+				seed_hash = "sha256";
+				break;
+			case 48:
+				seed_hash = "sha384";
+				break;
+			case 64:
+				seed_hash = "sha512";
+				break;
+			default:
+				pr_err("Seed size %d cannot be processed\n",
+				       seedsize);
+				goto dealloc;
+				break;
+			}
+		}
+
+		lrng_hash = _lrng_kcapi_hash_alloc(seed_hash);
+		if (IS_ERR(lrng_hash)) {
+			ret = ERR_CAST(lrng_hash);
+			goto dealloc;
+		}
+
+		if (seedsize != _lrng_kcapi_hash_digestsize(lrng_hash)) {
+			pr_err("Seed hash output size not equal to DRNG seed size\n");
+			_lrng_kcapi_hash_free(lrng_hash);
+			ret = ERR_PTR(-EINVAL);
+			goto dealloc;
+		}
+
+		lrng_drng_info->lrng_hash = lrng_hash;
+
+		pr_info("Seed hash %s allocated\n", seed_hash);
+	} else {
+		lrng_drng_info->lrng_hash = NULL;
+	}
+
+	pr_info("Kernel crypto API DRNG %s allocated\n", drng_name);
+
+	return lrng_drng_info;
+
+dealloc:
+	crypto_free_rng(kcapi_rng);
+free:
+	kfree(lrng_drng_info);
+	return ret;
+}
+
+static void lrng_kcapi_drng_dealloc(void *drng)
+{
+	struct lrng_drng_info *lrng_drng_info = (struct lrng_drng_info *)drng;
+	struct crypto_rng *kcapi_rng = lrng_drng_info->kcapi_rng;
+	struct lrng_hash_info *lrng_hash = lrng_drng_info->lrng_hash;
+
+	crypto_free_rng(kcapi_rng);
+	if (lrng_hash) {
+		_lrng_kcapi_hash_free(lrng_hash);
+		pr_info("Seed hash %s deallocated\n", seed_hash);
+	}
+	kfree(lrng_drng_info);
+	pr_info("DRNG %s deallocated\n", drng_name);
+}
+
+static const char *lrng_kcapi_drng_name(void)
+{
+	return drng_name;
+}
+
+static const char *lrng_kcapi_pool_hash(void)
+{
+	return pool_hash;
+}
+
+const static struct lrng_crypto_cb lrng_kcapi_crypto_cb = {
+	.lrng_drng_name			= lrng_kcapi_drng_name,
+	.lrng_hash_name			= lrng_kcapi_pool_hash,
+	.lrng_drng_alloc		= lrng_kcapi_drng_alloc,
+	.lrng_drng_dealloc		= lrng_kcapi_drng_dealloc,
+	.lrng_drng_seed_helper		= lrng_kcapi_drng_seed_helper,
+	.lrng_drng_generate_helper	= lrng_kcapi_drng_generate_helper,
+	.lrng_hash_alloc		= lrng_kcapi_hash_alloc,
+	.lrng_hash_dealloc		= lrng_kcapi_hash_dealloc,
+	.lrng_hash_digestsize		= lrng_kcapi_hash_digestsize,
+	.lrng_hash_buffer		= lrng_kcapi_hash_buffer,
+};
+
+static int __init lrng_kcapi_init(void)
+{
+	return lrng_set_drng_cb(&lrng_kcapi_crypto_cb);
+}
+static void __exit lrng_kcapi_exit(void)
+{
+	lrng_set_drng_cb(NULL);
+}
+
+late_initcall(lrng_kcapi_init);
+module_exit(lrng_kcapi_exit);
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
+MODULE_DESCRIPTION("Linux Random Number Generator - kernel crypto API DRNG backend");
-- 
2.24.1





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v29 08/12] crypto: provide access to a static Jitter RNG state
  2020-01-19 21:12         ` [PATCH v29 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                             ` (6 preceding siblings ...)
  2020-01-19 21:16           ` [PATCH v29 07/12] LRNG - add kernel crypto API PRNG extension Stephan Müller
@ 2020-01-19 21:17           ` Stephan Müller
  2020-01-19 21:18           ` [PATCH v29 09/12] LRNG - add Jitter RNG fast noise source Stephan Müller
                             ` (3 subsequent siblings)
  11 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2020-01-19 21:17 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap, Julia Lawall, Dan Carpenter

To support the LRNG operation which uses the Jitter RNG separately
from the kernel crypto API, at a time where potentially the regular
memory management is not yet initialized, the Jitter RNG needs to
provide a state whose memory is defined at compile time. As only once
instance will ever be needed by the LRNG, define once static memory
block which is solely to be used by the LRNG.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 crypto/jitterentropy-kcapi.c                  |  3 +--
 crypto/jitterentropy.c                        | 25 ++++++++++++++++++-
 .../crypto/internal}/jitterentropy.h          |  3 +++
 3 files changed, 28 insertions(+), 3 deletions(-)
 rename {crypto => include/crypto/internal}/jitterentropy.h (84%)

diff --git a/crypto/jitterentropy-kcapi.c b/crypto/jitterentropy-kcapi.c
index a5ce8f96790f..11b00e9f37f3 100644
--- a/crypto/jitterentropy-kcapi.c
+++ b/crypto/jitterentropy-kcapi.c
@@ -43,8 +43,7 @@
 #include <linux/time.h>
 #include <linux/crypto.h>
 #include <crypto/internal/rng.h>
-
-#include "jitterentropy.h"
+#include <crypto/internal/jitterentropy.h>
 
 /***************************************************************************
  * Helper function
diff --git a/crypto/jitterentropy.c b/crypto/jitterentropy.c
index 042157f0d28b..529c9db13e64 100644
--- a/crypto/jitterentropy.c
+++ b/crypto/jitterentropy.c
@@ -103,7 +103,7 @@ struct rand_data {
  * Helper functions
  ***************************************************************************/
 
-#include "jitterentropy.h"
+#include <crypto/internal/jitterentropy.h>
 
 /**
  * Update of the loop count used for the next round of
@@ -639,3 +639,26 @@ int jent_entropy_init(void)
 
 	return 0;
 }
+
+struct rand_data *jent_lrng_entropy_collector(void)
+{
+	static unsigned char lrng_jent_mem[JENT_MEMORY_SIZE];
+	static struct rand_data lrng_jent_state = {
+		.data		= 0,
+		.old_data	= 0,
+		.prev_time	= 0,
+		.last_delta	= 0,
+		.last_delta2	= 0,
+		.osr		= 1,
+		.mem		= lrng_jent_mem,
+		.memlocation	= 0,
+		.memblocks	= JENT_MEMORY_BLOCKSIZE,
+		.memblocksize	= JENT_MEMORY_BLOCKS,
+		.memaccessloops	= JENT_MEMORY_ACCESSLOOPS,
+	};
+
+	if (jent_entropy_init())
+		return NULL;
+
+	return &lrng_jent_state;
+}
diff --git a/crypto/jitterentropy.h b/include/crypto/internal/jitterentropy.h
similarity index 84%
rename from crypto/jitterentropy.h
rename to include/crypto/internal/jitterentropy.h
index c83fff32d130..6e07d86eac82 100644
--- a/crypto/jitterentropy.h
+++ b/include/crypto/internal/jitterentropy.h
@@ -15,3 +15,6 @@ extern int jent_read_entropy(struct rand_data *ec, unsigned char *data,
 extern struct rand_data *jent_entropy_collector_alloc(unsigned int osr,
 						      unsigned int flags);
 extern void jent_entropy_collector_free(struct rand_data *entropy_collector);
+
+/* Access to statically allocated Jitter RNG instance */
+extern struct rand_data *jent_lrng_entropy_collector(void);
-- 
2.24.1





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v29 09/12] LRNG - add Jitter RNG fast noise source
  2020-01-19 21:12         ` [PATCH v29 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                             ` (7 preceding siblings ...)
  2020-01-19 21:17           ` [PATCH v29 08/12] crypto: provide access to a static Jitter RNG state Stephan Müller
@ 2020-01-19 21:18           ` Stephan Müller
  2020-01-19 21:18           ` [PATCH v29 10/12] LRNG - add SP800-90B compliant health tests Stephan Müller
                             ` (2 subsequent siblings)
  11 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2020-01-19 21:18 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap, Julia Lawall, Dan Carpenter

The Jitter RNG fast noise source implemented as part of the kernel
crypto API is queried for 256 bits of entropy at the time the seed
buffer managed by the LRNG is about to be filled.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Kconfig     | 12 +++++
 drivers/char/lrng/Makefile    |  1 +
 drivers/char/lrng/lrng_jent.c | 88 +++++++++++++++++++++++++++++++++++
 3 files changed, 101 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_jent.c

diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
index 7afc965a4d52..4684e838f011 100644
--- a/drivers/char/lrng/Kconfig
+++ b/drivers/char/lrng/Kconfig
@@ -94,4 +94,16 @@ config LRNG_KCAPI
 	  provided by the selected kernel crypto API RNG.
 endif # LRNG_DRNG_SWITCH
 
+config LRNG_JENT
+	bool "Enable Jitter RNG as LRNG Seed Source"
+	depends on CRYPTO
+	select CRYPTO_JITTERENTROPY
+	help
+	  The Linux RNG may use the Jitter RNG as noise source. Enabling
+	  this option enables the use of the Jitter RNG. Its default
+	  entropy level is 16 bits of entropy per 256 data bits delivered
+	  by the Jitter RNG. This entropy level can be changed at boot
+	  time or at runtime with the lrng_base.jitterrng configuration
+	  variable.
+
 endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index 94b2dfb2dfdb..4f5b6f38f0c4 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -13,3 +13,4 @@ obj-$(CONFIG_SYSCTL)		+= lrng_proc.o
 obj-$(CONFIG_LRNG_DRNG_SWITCH)	+= lrng_switch.o
 obj-$(CONFIG_LRNG_DRBG)		+= lrng_drbg.o
 obj-$(CONFIG_LRNG_KCAPI)	+= lrng_kcapi.o
+obj-$(CONFIG_LRNG_JENT)		+= lrng_jent.o
diff --git a/drivers/char/lrng/lrng_jent.c b/drivers/char/lrng/lrng_jent.c
new file mode 100644
index 000000000000..225505271fcb
--- /dev/null
+++ b/drivers/char/lrng/lrng_jent.c
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG Fast Noise Source: Jitter RNG
+ *
+ * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/types.h>
+#include <crypto/internal/jitterentropy.h>
+
+#include "lrng_internal.h"
+
+/*
+ * Estimated entropy of data is a 16th of LRNG_DRNG_SECURITY_STRENGTH_BITS.
+ * Albeit a full entropy assessment is provided for the noise source indicating
+ * that it provides high entropy rates and considering that it deactivates
+ * when it detects insufficient hardware, the chosen under estimation of
+ * entropy is considered to be acceptable to all reviewers.
+ */
+static u32 jitterrng = LRNG_DRNG_SECURITY_STRENGTH_BITS>>4;
+module_param(jitterrng, uint, 0644);
+MODULE_PARM_DESC(jitterrng, "Entropy in bits of 256 data bits from Jitter RNG noise source");
+
+/**
+ * lrng_get_jent() - Get Jitter RNG entropy
+ *
+ * @outbuf: buffer to store entropy
+ * @outbuflen: length of buffer
+ *
+ * Return:
+ * * > 0 on success where value provides the added entropy in bits
+ * * 0 if no fast source was available
+ */
+static struct rand_data *lrng_jent_state;
+
+u32 lrng_get_jent(u8 *outbuf, unsigned int outbuflen)
+{
+	int ret;
+	u32 ent_bits = jitterrng;
+	unsigned long flags;
+	static DEFINE_SPINLOCK(lrng_jent_lock);
+	static int lrng_jent_initialized = 0;
+
+	spin_lock_irqsave(&lrng_jent_lock, flags);
+
+	if (!ent_bits || (lrng_jent_initialized == -1)) {
+		spin_unlock_irqrestore(&lrng_jent_lock, flags);
+		return 0;
+	}
+
+	if (!lrng_jent_initialized) {
+		lrng_jent_state = jent_lrng_entropy_collector();
+		if (!lrng_jent_state) {
+			jitterrng = 0;
+			lrng_jent_initialized = -1;
+			spin_unlock_irqrestore(&lrng_jent_lock, flags);
+			pr_info("Jitter RNG unusable on current system\n");
+			return 0;
+		}
+		lrng_jent_initialized = 1;
+		pr_debug("Jitter RNG working on current system\n");
+	}
+	ret = jent_read_entropy(lrng_jent_state, outbuf, outbuflen);
+	spin_unlock_irqrestore(&lrng_jent_lock, flags);
+
+	if (ret) {
+		pr_debug("Jitter RNG failed with %d\n", ret);
+		return 0;
+	}
+
+	/* Obtain entropy statement */
+	if (outbuflen != LRNG_DRNG_SECURITY_STRENGTH_BYTES)
+		ent_bits = (ent_bits * outbuflen<<3) /
+			   LRNG_DRNG_SECURITY_STRENGTH_BITS;
+	/* Cap entropy to buffer size in bits */
+	ent_bits = min_t(u32, ent_bits, outbuflen<<3);
+	pr_debug("obtained %u bits of entropy from Jitter RNG noise source\n",
+		 ent_bits);
+
+	return ent_bits;
+}
+
+u32 lrng_jent_entropylevel(void)
+{
+	return min_t(u32, jitterrng, LRNG_DRNG_SECURITY_STRENGTH_BITS);
+}
-- 
2.24.1





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v29 10/12] LRNG - add SP800-90B compliant health tests
  2020-01-19 21:12         ` [PATCH v29 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                             ` (8 preceding siblings ...)
  2020-01-19 21:18           ` [PATCH v29 09/12] LRNG - add Jitter RNG fast noise source Stephan Müller
@ 2020-01-19 21:18           ` Stephan Müller
  2020-01-19 21:19           ` [PATCH v29 11/12] LRNG - add interface for gathering of raw entropy Stephan Müller
  2020-01-19 21:20           ` [PATCH v29 12/12] LRNG - add power-on and runtime self-tests Stephan Müller
  11 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2020-01-19 21:18 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap, Julia Lawall, Dan Carpenter

Implement health tests for LRNG's slow noise sources as mandated by
SP-800-90B The file contains the following health tests:

- stuck test: The stuck test calculates the first, second and third
  discrete derivative of the time stamp to be processed by the LFSR.
  Only if all three values are non-zero, the received time delta is
  considered to be non-stuck.

- SP800-90B Repetition Count Test (RCT): The LRNG uses an enhanced
  version of the RCT specified in SP800-90B section 4.4.1. Instead of
  counting identical back-to-back values, the input to the RCT is the
  counting of the stuck values during the processing of received
  interrupt events. The RCT is applied with alpha=2^-30 compliant to
  the recommendation of FIPS 140-2 IG 9.8. During the counting operation,
  the LRNG always calculates the RCT cut-off value of C. If that value
  exceeds the allowed cut-off value, the LRNG will trigger the health
  test failure discussed below. An error is logged to the kernel log
  that such RCT failure occurred. This test is only applied and
  enforced in FIPS mode, i.e. when the kernel compiled with
  CONFIG_CONFIG_FIPS is started with fips=1.

- SP800-90B Adaptive Proportion Test (APT): The LRNG implements the
  APT as defined in SP800-90B section 4.4.2. The applied significance
  level again is alpha=2^-30 compliant to the recommendation of FIPS
  140-2 IG 9.8.

The aforementioned health tests are applied to the first 1,024 time stamps
obtained from interrupt events. In case one error is identified for either
the RCT, or the APT, the collected entropy is invalidated and the
SP800-90B startup health test is restarted.

As long as the SP800-90B startup health test is not completed, all LRNG
random number output interfaces that may block will block and not generate
any data. This implies that only those potentially blocking interfaces are
defined to provide random numbers that are seeded with the interrupt noise
source being SP800-90B compliant. All other output interfaces will not be
affected by the SP800-90B startup test and thus are not considered
SP800-90B compliant.

At runtime, the SP800-90B APT and RCT are applied to each time stamp
generated for a received interrupt. When either the APT and RCT indicates
a noise source failure, the LRNG is reset to a state it has immediately
after boot:

- all entropy counters are set to zero

- the SP800-90B startup tests are re-performed which implies that
getrandom(2) would block again until new entropy was collected

To summarize, the following rules apply:

• SP800-90B compliant output interfaces

  - /dev/random

  - getrandom(2) system call

  -  get_random_bytes kernel-internal interface when being triggered by
     the callback registered with add_random_ready_callback

• SP800-90B non-compliant output interfaces

  - /dev/urandom

  - get_random_bytes kernel-internal interface called directly

  - randomize_page kernel-internal interface

  - get_random_u32 and get_random_u64 kernel-internal interfaces

  - get_random_u32_wait, get_random_u64_wait, get_random_int_wait, and
    get_random_long_wait kernel-internal interfaces

If either the RCT, or the APT health test fails irrespective whether
during initialization or runtime, the following actions occur:

  1. The entropy of the entire entropy pool is invalidated.

  2. All DRNGs are reset which imply that they are treated as being
     not seeded and require a reseed during next invocation.

  3. The SP800-90B startup health test are initiated with all
     implications of the startup tests. That implies that from that point
     on, new events must be observed and its entropy must be inserted into
     the entropy pool before random numbers are calculated from the
     entropy pool.

Further details on the SP800-90B compliance and the availability of all
test tools required to perform all tests mandated by SP800-90B are
provided at [1].

The entire health testing code is compile-time configurable.

The patch provides a CONFIG_BROKEN configuration of the APT / RCT cutoff
values which have a high likelihood to trigger the health test failure.
The BROKEN APT cutoff is set to the exact mean of the expected value if
the time stamps are equally distributed (512 time stamps divided by 16
possible values due to using the 4 LSB of the time stamp). The BROKEN
RCT cutoff value is set to 1 which is likely to be triggered during
regular operation.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Kconfig       |  56 +++++
 drivers/char/lrng/Makefile      |   1 +
 drivers/char/lrng/lrng_health.c | 407 ++++++++++++++++++++++++++++++++
 3 files changed, 464 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_health.c

diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
index 4684e838f011..323c657f7005 100644
--- a/drivers/char/lrng/Kconfig
+++ b/drivers/char/lrng/Kconfig
@@ -106,4 +106,60 @@ config LRNG_JENT
 	  time or at runtime with the lrng_base.jitterrng configuration
 	  variable.
 
+config LRNG_HEALTH_TESTS
+	bool "Enable noise source online health tests"
+	help
+	  The online health tests validate the noise source at
+	  runtime for fatal errors. These tests include SP800-90B
+	  compliant tests which are invoked if the system is booted
+	  with fips=1. In case of fatal errors during active
+	  SP800-90B tests, the issue is logged and the noise
+	  data is discarded. These tests are required for full
+	  compliance with SP800-90B.
+
+	  If unsure, say Y.
+
+config LRNG_RCT_BROKEN
+	bool "SP800-90B RCT with dangerous low cutoff value"
+	depends on LRNG_HEALTH_TESTS
+	depends on BROKEN
+	default n
+	help
+	  This option enables a dangerously low SP800-90B repetitive
+	  count test (RCT) cutoff value which makes it very likely
+	  that the RCT is triggered to raise a self test failure.
+
+	  This option is ONLY intended for developers wanting to
+	  test the effectiveness of the SP800-90B RCT health test.
+
+	  If unsure, say N.
+
+config LRNG_APT_BROKEN
+	bool "SP800-90B APT with dangerous low cutoff value"
+	depends on LRNG_HEALTH_TESTS
+	depends on BROKEN
+	default n
+	help
+	  This option enables a dangerously low SP800-90B adaptive
+	  proportion test (APT) cutoff value which makes it very
+	  likely that the RCT is triggered to raise a self test
+	  failure.
+
+	  This option is ONLY intended for developers wanting to
+	  test the effectiveness of the SP800-90B APT health test.
+
+	  If unsure, say N.
+
+# Default taken from SP800-90B sec 4.4.1 - significance level 2^-30
+config LRNG_RCT_CUTOFF
+	int
+	default 31 if !LRNG_RCT_BROKEN
+	default 1 if LRNG_RCT_BROKEN
+
+# Default taken from SP800-90B sec 4.4.2 - significance level 2^-30
+config LRNG_APT_CUTOFF
+	int
+	default 325 if !LRNG_APT_BROKEN
+	default 32 if LRNG_APT_BROKEN
+
 endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index 4f5b6f38f0c4..c3008763dd14 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -14,3 +14,4 @@ obj-$(CONFIG_LRNG_DRNG_SWITCH)	+= lrng_switch.o
 obj-$(CONFIG_LRNG_DRBG)		+= lrng_drbg.o
 obj-$(CONFIG_LRNG_KCAPI)	+= lrng_kcapi.o
 obj-$(CONFIG_LRNG_JENT)		+= lrng_jent.o
+obj-$(CONFIG_LRNG_HEALTH_TESTS)	+= lrng_health.o
diff --git a/drivers/char/lrng/lrng_health.c b/drivers/char/lrng/lrng_health.c
new file mode 100644
index 000000000000..7817aa6f3357
--- /dev/null
+++ b/drivers/char/lrng/lrng_health.c
@@ -0,0 +1,407 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * Linux Random Number Generator (LRNG) Health Testing
+ *
+ * Copyright (C) 2019 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/fips.h>
+#include <linux/module.h>
+
+#include "lrng_internal.h"
+
+/* Stuck Test */
+struct lrng_stuck_test {
+	u32 last_time;		/* Stuck test: time of previous IRQ */
+	u32 last_delta;		/* Stuck test: delta of previous IRQ */
+	u32 last_delta2;	/* Stuck test: 2. time derivation of prev IRQ */
+};
+
+/* Repetition Count Test */
+struct lrng_rct {
+	atomic_t rct_count;	/* Number of stuck values */
+};
+
+/* Adaptive Proportion Test */
+struct lrng_apt {
+	/* Data window size */
+#define LRNG_APT_WINDOW_SIZE	512
+	/* LSB of time stamp to process */
+#define LRNG_APT_LSB		16
+#define LRNG_APT_WORD_MASK	(LRNG_APT_LSB - 1)
+	atomic_t apt_count;		/* APT counter */
+	atomic_t apt_base;		/* APT base reference */
+
+	atomic_t apt_trigger;
+	bool apt_base_set;	/* Is APT base set? */
+};
+
+/* The health test code must operate lock-less */
+struct lrng_health {
+	struct lrng_rct rct;
+	struct lrng_apt apt;
+
+	bool health_test_enabled;
+
+	/* SP800-90B startup health tests */
+#define LRNG_SP80090B_STARTUP_SAMPLES  1024
+#define LRNG_SP80090B_STARTUP_BLOCKS   ((LRNG_SP80090B_STARTUP_SAMPLES + \
+					 LRNG_APT_WINDOW_SIZE - 1) /    \
+					LRNG_APT_WINDOW_SIZE)
+	bool sp80090b_startup_done;
+	atomic_t sp80090b_startup_blocks;
+};
+
+static struct lrng_health lrng_health = {
+	.rct.rct_count = ATOMIC_INIT(0),
+
+	.apt.apt_count = ATOMIC_INIT(0),
+	.apt.apt_base = ATOMIC_INIT(-1),
+	.apt.apt_trigger = ATOMIC_INIT(LRNG_APT_WINDOW_SIZE),
+	.apt.apt_base_set = false,
+
+	.health_test_enabled = true,
+
+	.sp80090b_startup_blocks = ATOMIC_INIT(LRNG_SP80090B_STARTUP_BLOCKS),
+	.sp80090b_startup_done = false,
+};
+
+static DEFINE_PER_CPU(struct lrng_stuck_test, lrng_stuck_test);
+
+static inline bool lrng_sp80090b_health_requested(void)
+{
+	/* Health tests are only requested in FIPS mode */
+	return fips_enabled;
+}
+
+static inline bool lrng_sp80090b_health_enabled(void)
+{
+	struct lrng_health *health = &lrng_health;
+
+	return lrng_sp80090b_health_requested() && health->health_test_enabled;
+}
+
+/***************************************************************************
+ * SP800-90B Compliance
+ *
+ * If the Linux-RNG is booted into FIPS mode, the following interfaces
+ * provide an SP800-90B compliant noise source:
+ *
+ * * /dev/random
+ * * getrandom(2)
+ * * get_random_bytes when using it in conjunction with
+ *   add_random_ready_callback
+ *
+ * All other interfaces, including /dev/urandom or get_random_bytes without
+ * the add_random_ready_callback cannot claim to use an SP800-90B compliant
+ * noise source.
+ ***************************************************************************/
+
+/*
+ * Perform SP800-90B startup testing
+ */
+static inline void lrng_sp80090b_startup(struct lrng_health *health)
+{
+	if (!health->sp80090b_startup_done &&
+	    atomic_dec_and_test(&health->sp80090b_startup_blocks)) {
+		health->sp80090b_startup_done = true;
+		pr_info("SP800-90B startup health tests completed\n");
+		lrng_init_ops(0);
+
+		/*
+		 * Force a reseed of DRNGs to ensure they are seeded with
+		 * entropy that passed the SP800-90B health tests.
+		 * As the DRNG always will reseed before generating
+		 * random numbers, it does not need a reseed trigger.
+		 */
+		lrng_drng_force_reseed();
+	}
+}
+
+/*
+ * Handle failure of SP800-90B startup testing
+ */
+static inline void lrng_sp80090b_startup_failure(struct lrng_health *health)
+{
+	/* Reset of LRNG and its entropy - NOTE: we are in atomic context */
+	lrng_reset();
+
+	/*
+	 * Reset the SP800-90B startup test.
+	 *
+	 * NOTE SP800-90B section 4.3 bullet 4 does not specify what
+	 * exactly is to be done in case of failure! Thus, we do what
+	 * makes sense, i.e. restarting the health test and thus gating
+	 * the output function of /dev/random and getrandom(2).
+	 */
+	atomic_set(&health->sp80090b_startup_blocks,
+		   LRNG_SP80090B_STARTUP_BLOCKS);
+}
+
+/*
+ * Handle failure of SP800-90B runtime testing
+ */
+static inline void lrng_sp80090b_runtime_failure(struct lrng_health *health)
+{
+	lrng_sp80090b_startup_failure(health);
+	health->sp80090b_startup_done = false;
+}
+
+static inline void lrng_sp80090b_failure(struct lrng_health *health)
+{
+	if (health->sp80090b_startup_done) {
+		pr_err("SP800-90B runtime health test failure - invalidating all existing entropy and initiate SP800-90B startup\n");
+		lrng_sp80090b_runtime_failure(health);
+	} else {
+		pr_err("SP800-90B startup test failure - resetting\n");
+		lrng_sp80090b_startup_failure(health);
+	}
+}
+
+/*
+ * Is the SP800-90B startup testing complete?
+ *
+ * This function is called by the LRNG to determine whether to unblock
+ * a certain user interface. Therefore, only the potentially blocking
+ * user interfaces are considered SP800-90B compliant.
+ */
+bool lrng_sp80090b_startup_complete(void)
+{
+	struct lrng_health *health = &lrng_health;
+
+	return (lrng_sp80090b_health_enabled()) ? health->sp80090b_startup_done:
+						  true;
+}
+
+bool lrng_sp80090b_compliant(void)
+{
+	struct lrng_health *health = &lrng_health;
+
+	return lrng_sp80090b_health_enabled() && health->sp80090b_startup_done;
+}
+
+/***************************************************************************
+ * Adaptive Proportion Test
+ *
+ * This test complies with SP800-90B section 4.4.2.
+ ***************************************************************************/
+
+/*
+ * Reset the APT counter
+ *
+ * @health [in] Reference to health state
+ */
+static inline void lrng_apt_reset(struct lrng_health *health,
+				  unsigned int time_masked)
+{
+	struct lrng_apt *apt = &health->apt;
+
+	pr_debug("APT value %d for base %d\n",
+		 atomic_read(&apt->apt_count), atomic_read(&apt->apt_base));
+
+	/* Reset APT */
+	atomic_set(&apt->apt_count, 0);
+	atomic_set(&apt->apt_base, time_masked);
+}
+
+static inline void lrng_apt_restart(struct lrng_health *health)
+{
+	struct lrng_apt *apt = &health->apt;
+
+	atomic_set(&apt->apt_trigger, LRNG_APT_WINDOW_SIZE);
+}
+
+/*
+ * Insert a new entropy event into APT
+ *
+ * This function does is void as it does not decide about the fate of a time
+ * stamp. An APT failure can only happen at the same time of a stuck test
+ * failure. Thus, the stuck failure will already decide how the time stamp
+ * is handled.
+ *
+ * @health [in] Reference to health state
+ * @now_time [in] Time stamp to process
+ */
+static inline void lrng_apt_insert(struct lrng_health *health,
+				   unsigned int now_time)
+{
+	struct lrng_apt *apt = &health->apt;
+
+	if (!lrng_sp80090b_health_requested())
+		return;
+
+	now_time &= LRNG_APT_WORD_MASK;
+
+	/* Initialization of APT */
+	if (!apt->apt_base_set) {
+		atomic_set(&apt->apt_base, now_time);
+		apt->apt_base_set = true;
+		return;
+	}
+
+	if (now_time == (unsigned int)atomic_read(&apt->apt_base)) {
+		u32 apt_val = (u32)atomic_inc_return_relaxed(&apt->apt_count);
+
+		if (apt_val >= CONFIG_LRNG_APT_CUTOFF)
+			lrng_sp80090b_failure(health);
+	}
+
+	if (atomic_dec_and_test(&apt->apt_trigger)) {
+		lrng_apt_restart(health);
+		lrng_apt_reset(health, now_time);
+		lrng_sp80090b_startup(health);
+	}
+}
+
+/***************************************************************************
+ * Repetition Count Test
+ *
+ * The LRNG uses an enhanced version of the Repetition Count Test
+ * (RCT) specified in SP800-90B section 4.4.1. Instead of counting identical
+ * back-to-back values, the input to the RCT is the counting of the stuck
+ * values while filling the entropy pool.
+ *
+ * The RCT is applied with an alpha of 2^-30 compliant to FIPS 140-2 IG 9.8.
+ *
+ * During the counting operation, the LRNG always calculates the RCT
+ * cut-off value of C. If that value exceeds the allowed cut-off value,
+ * the LRNG will invalidate all entropy for the entropy pool which implies
+ * that no data can be extracted from the entropy pool unless new entropy
+ * is received.
+ ***************************************************************************/
+
+/*
+ * Hot code path - Insert data for Repetition Count Test
+ *
+ * @health: Reference to health information
+ * @stuck: Decision of stuck test
+ */
+static inline void lrng_rct(struct lrng_health *health, int stuck)
+{
+	struct lrng_rct *rct = &health->rct;
+
+	if (!lrng_sp80090b_health_requested())
+		return;
+
+	if (stuck) {
+		u32 rct_count = atomic_add_return_relaxed(1, &rct->rct_count);
+
+		pr_debug("RCT count: %u\n", rct_count);
+
+		/*
+		 * The cutoff value is based on the following consideration:
+		 * alpha = 2^-30 as recommended in FIPS 140-2 IG 9.8.
+		 * In addition, we imply an entropy value H of 1 bit as this
+		 * is the minimum entropy required to provide full entropy.
+		 *
+		 * Note, rct_count (which equals to value B in the
+		 * pseudo code of SP800-90B section 4.4.1) starts with zero.
+		 * Hence we need to subtract one from the cutoff value as
+		 * calculated following SP800-90B.
+		 */
+		if (rct_count >= CONFIG_LRNG_RCT_CUTOFF) {
+			atomic_set(&rct->rct_count, 0);
+
+			/*
+			 * APT must start anew as we consider all previously
+			 * recorded data to contain no entropy.
+			 */
+			lrng_apt_restart(health);
+
+			lrng_sp80090b_failure(health);
+		}
+	} else {
+		atomic_set(&rct->rct_count, 0);
+	}
+}
+
+/***************************************************************************
+ * Stuck Test
+ *
+ * Checking the:
+ *      1st derivative of the event occurrence (time delta)
+ *      2nd derivative of the event occurrence (delta of time deltas)
+ *      3rd derivative of the event occurrence (delta of delta of time deltas)
+ *
+ * All values must always be non-zero. The stuck test is only valid disabled if
+ * high-resolution time stamps are identified after initialization.
+ ***************************************************************************/
+
+static inline u32 lrng_delta(u32 prev, u32 next)
+{
+	/*
+	 * Note that this (unsigned) subtraction does yield the correct value
+	 * in the wraparound-case, i.e. when next < prev.
+	 */
+	return (next - prev);
+}
+
+/*
+ * Hot code path
+ *
+ * @health: Reference to health information
+ * @now: Event time
+ * @return: 0 event occurrence not stuck (good time stamp)
+ *	    != 0 event occurrence stuck (reject time stamp)
+ */
+static inline int lrng_irq_stuck(struct lrng_stuck_test *stuck, u32 now_time)
+{
+	u32 delta = lrng_delta(stuck->last_time, now_time);
+	u32 delta2 = lrng_delta(stuck->last_delta, delta);
+	u32 delta3 = lrng_delta(stuck->last_delta2, delta2);
+
+	stuck->last_time = now_time;
+	stuck->last_delta = delta;
+	stuck->last_delta2 = delta2;
+
+	if (!delta || !delta2 || !delta3)
+		return 1;
+
+	return 0;
+}
+
+/***************************************************************************
+ * Health test interfaces
+ ***************************************************************************/
+
+/*
+ * Disable all health tests
+ */
+void lrng_health_disable(void)
+{
+	struct lrng_health *health = &lrng_health;
+
+	health->health_test_enabled = false;
+
+	if (lrng_sp80090b_health_requested())
+		pr_warn("SP800-90B compliance requested but the Linux RNG is NOT SP800-90B compliant\n");
+}
+
+/*
+ * Hot code path - Perform health test on time stamp received from an event
+ *
+ * @now_time Time stamp
+ */
+enum lrng_health_res lrng_health_test(u32 now_time)
+{
+	struct lrng_health *health = &lrng_health;
+	struct lrng_stuck_test *stuck_test = this_cpu_ptr(&lrng_stuck_test);
+	int stuck;
+
+	if (!health->health_test_enabled)
+		return lrng_health_pass;
+
+	lrng_apt_insert(health, now_time);
+
+	stuck = lrng_irq_stuck(stuck_test, now_time);
+	lrng_rct(health, stuck);
+	if (stuck) {
+		/* SP800-90B disallows using a failing health test time stamp */
+		return lrng_sp80090b_health_requested() ?
+			lrng_health_fail_drop : lrng_health_fail_use;
+	}
+
+	return lrng_health_pass;
+}
-- 
2.24.1





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v29 11/12] LRNG - add interface for gathering of raw entropy
  2020-01-19 21:12         ` [PATCH v29 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                             ` (9 preceding siblings ...)
  2020-01-19 21:18           ` [PATCH v29 10/12] LRNG - add SP800-90B compliant health tests Stephan Müller
@ 2020-01-19 21:19           ` Stephan Müller
  2020-01-19 21:20           ` [PATCH v29 12/12] LRNG - add power-on and runtime self-tests Stephan Müller
  11 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2020-01-19 21:19 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap, Julia Lawall, Dan Carpenter

The test interface allows a privileged process to capture the raw
unconditioned noise that is collected by the LRNG for statistical
analysis. Such testing allows the analysis how much entropy
the interrupt noise source provides on a given platform.
Extracted noise data is not used to seed the LRNG. This
is a test interface and not appropriate for production systems.
Yet, the interface is considered to be sufficiently secured for
production systems.

Access to the data is given through the lrng_raw debugfs file. The
data buffer should be multiples of sizeof(u32) to fill the entire
buffer. Using the option lrng_testing.boot_test=1 the raw noise of
the first 1000 entropy events since boot can be sampled.

This test interface allows generating the data required for
analysis whether the LRNG is in compliance with SP800-90B
sections 3.1.3 and 3.1.4.

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Roman Drahtmüller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Kconfig        |  16 ++
 drivers/char/lrng/Makefile       |   1 +
 drivers/char/lrng/lrng_testing.c | 269 +++++++++++++++++++++++++++++++
 3 files changed, 286 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_testing.c

diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
index 323c657f7005..014ee82df79a 100644
--- a/drivers/char/lrng/Kconfig
+++ b/drivers/char/lrng/Kconfig
@@ -162,4 +162,20 @@ config LRNG_APT_CUTOFF
 	default 325 if !LRNG_APT_BROKEN
 	default 32 if LRNG_APT_BROKEN
 
+config LRNG_TESTING
+	bool "Enable entropy test interface to LRNG noise source"
+	depends on DEBUG_FS
+	help
+	  The test interface allows a privileged process to capture
+	  the raw unconditioned noise that is collected by the LRNG
+	  for statistical analysis. Extracted noise data is not used
+	  to seed the LRNG.
+
+	  The raw noise data can be obtained using the lrng_raw
+	  debugfs file. Using the option lrng_testing.boot_test=1
+	  the raw noise of the first 1000 entropy events since boot
+	  can be sampled.
+
+	  If unsure, say N.
+
 endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index c3008763dd14..b2ce1979dc4b 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -15,3 +15,4 @@ obj-$(CONFIG_LRNG_DRBG)		+= lrng_drbg.o
 obj-$(CONFIG_LRNG_KCAPI)	+= lrng_kcapi.o
 obj-$(CONFIG_LRNG_JENT)		+= lrng_jent.o
 obj-$(CONFIG_LRNG_HEALTH_TESTS)	+= lrng_health.o
+obj-$(CONFIG_LRNG_TESTING)	+= lrng_testing.o
diff --git a/drivers/char/lrng/lrng_testing.c b/drivers/char/lrng/lrng_testing.c
new file mode 100644
index 000000000000..996fc665a0a0
--- /dev/null
+++ b/drivers/char/lrng/lrng_testing.c
@@ -0,0 +1,269 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * Linux Random Number Generator (LRNG) Raw entropy collection tool
+ *
+ * Copyright (C) 2019 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/atomic.h>
+#include <linux/bug.h>
+#include <linux/debugfs.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/sched/signal.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+#include <linux/workqueue.h>
+#include <asm/errno.h>
+
+#include "lrng_internal.h"
+
+#define LRNG_TESTING_RINGBUFFER_SIZE	1024
+#define LRNG_TESTING_RINGBUFFER_MASK	(LRNG_TESTING_RINGBUFFER_SIZE - 1)
+
+static u32 lrng_testing_rb[LRNG_TESTING_RINGBUFFER_SIZE];
+static u32 lrng_rb_reader = 0;
+static u32 lrng_rb_writer = 0;
+static atomic_t lrng_testing_enabled = ATOMIC_INIT(0);
+
+static DECLARE_WAIT_QUEUE_HEAD(lrng_raw_read_wait);
+static DEFINE_SPINLOCK(lrng_raw_lock);
+
+/*
+ * 0 ==> No boot test, gathering of runtime data allowed
+ * 1 ==> Boot test enabled and ready for collecting data, gathering runtime
+ *	 data is disabled
+ * 2 ==> Boot test completed and disabled, gathering of runtime data is
+ *	 disabled
+ */
+static u32 boot_test = 0;
+module_param(boot_test, uint, 0644);
+MODULE_PARM_DESC(boot_test, "Enable gathering boot time entropy of the first entropy events");
+
+static inline void lrng_raw_entropy_reset(void)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&lrng_raw_lock, flags);
+	lrng_rb_reader = 0;
+	lrng_rb_writer = 0;
+	spin_unlock_irqrestore(&lrng_raw_lock, flags);
+}
+
+static void lrng_raw_entropy_init(void)
+{
+	/*
+	 * The boot time testing implies we have a running test. If the
+	 * caller wants to clear it, he has to unset the boot_test flag
+	 * at runtime via sysfs to enable regular runtime testing
+	 */
+	if (boot_test)
+		return;
+
+	lrng_raw_entropy_reset();
+	atomic_set(&lrng_testing_enabled, 1);
+	pr_warn("Enabling raw entropy collection\n");
+}
+
+static void lrng_raw_entropy_fini(void)
+{
+	if (boot_test)
+		return;
+
+	atomic_set(&lrng_testing_enabled, 0);
+	lrng_raw_entropy_reset();
+	pr_warn("Disabling raw entropy collection\n");
+}
+
+bool lrng_raw_entropy_store(u32 value)
+{
+	unsigned long flags;
+
+	if (!atomic_read(&lrng_testing_enabled) && (boot_test != 1))
+		return false;
+
+	spin_lock_irqsave(&lrng_raw_lock, flags);
+
+	/*
+	 * Disable entropy testing for boot time testing after ring buffer
+	 * is filled.
+	 */
+	if (boot_test) {
+		if (lrng_rb_writer > LRNG_TESTING_RINGBUFFER_SIZE) {
+			boot_test = 2;
+			pr_warn_once("Boot time entropy collection test disabled\n");
+			spin_unlock_irqrestore(&lrng_raw_lock, flags);
+			return false;
+		}
+
+		if (lrng_rb_writer == 1)
+			pr_warn("Boot time entropy collection test enabled\n");
+	}
+
+	lrng_testing_rb[lrng_rb_writer & LRNG_TESTING_RINGBUFFER_MASK] = value;
+	lrng_rb_writer++;
+
+	spin_unlock_irqrestore(&lrng_raw_lock, flags);
+
+	if (wq_has_sleeper(&lrng_raw_read_wait))
+		wake_up_interruptible(&lrng_raw_read_wait);
+
+	return true;
+}
+
+static inline bool lrng_raw_have_data(void)
+{
+	return ((lrng_rb_writer & LRNG_TESTING_RINGBUFFER_MASK) !=
+		 (lrng_rb_reader & LRNG_TESTING_RINGBUFFER_MASK));
+}
+
+static int lrng_raw_entropy_reader(u8 *outbuf, u32 outbuflen)
+{
+	unsigned long flags;
+	int collected_data = 0;
+
+	lrng_raw_entropy_init();
+
+	while (outbuflen) {
+		spin_lock_irqsave(&lrng_raw_lock, flags);
+
+		/* We have no data or reached the writer. */
+		if (!lrng_rb_writer || (lrng_rb_writer == lrng_rb_reader)) {
+
+			spin_unlock_irqrestore(&lrng_raw_lock, flags);
+
+			/*
+			 * Now we gathered all boot data, enable regular data
+			 * collection.
+			 */
+			if (boot_test) {
+				boot_test = 0;
+				goto out;
+			}
+
+			wait_event_interruptible(lrng_raw_read_wait,
+						 lrng_raw_have_data());
+			if (signal_pending(current)) {
+				collected_data = -ERESTARTSYS;
+				goto out;
+			}
+
+			continue;
+		}
+
+		/* We copy out word-wise */
+		if (outbuflen < sizeof(u32)) {
+			spin_unlock_irqrestore(&lrng_raw_lock, flags);
+			goto out;
+		}
+
+		memcpy(outbuf, &lrng_testing_rb[lrng_rb_reader], sizeof(u32));
+		lrng_rb_reader++;
+
+		spin_unlock_irqrestore(&lrng_raw_lock, flags);
+
+		outbuf += sizeof(u32);
+		outbuflen -= sizeof(u32);
+		collected_data += sizeof(u32);
+	}
+
+out:
+	lrng_raw_entropy_fini();
+	return collected_data;
+}
+
+/**************************************************************************
+ * Debugfs interface
+ **************************************************************************/
+static int lrng_raw_extract_user(char __user *buf, size_t nbytes)
+{
+	u8 *tmp, *tmp_aligned;
+	int ret = 0, large_request = (nbytes > 256);
+
+	/*
+	 * The intention of this interface is for collecting at least
+	 * 1000 samples due to the SP800-90B requirements. So, we make no
+	 * effort in avoiding allocating more memory that actually needed
+	 * by the user. Hence, we allocate sufficient memory to always hold
+	 * that amount of data.
+	 */
+	tmp = kmalloc(LRNG_TESTING_RINGBUFFER_SIZE + sizeof(u32), GFP_KERNEL);
+	if (!tmp)
+		return -ENOMEM;
+
+	tmp_aligned = PTR_ALIGN(tmp, sizeof(u32));
+
+	while (nbytes) {
+		int i;
+
+		if (large_request && need_resched()) {
+			if (signal_pending(current)) {
+				if (ret == 0)
+					ret = -ERESTARTSYS;
+				break;
+			}
+			schedule();
+		}
+
+		i = min_t(int, nbytes, LRNG_TESTING_RINGBUFFER_SIZE);
+		i = lrng_raw_entropy_reader(tmp_aligned, i);
+		if (i <= 0) {
+			if (i < 0)
+				ret = i;
+			break;
+		}
+		if (copy_to_user(buf, tmp_aligned, i)) {
+			ret = -EFAULT;
+			break;
+		}
+
+		nbytes -= i;
+		buf += i;
+		ret += i;
+	}
+
+	kzfree(tmp);
+	return ret;
+}
+
+/* DebugFS operations and definition of the debugfs files */
+static ssize_t lrng_raw_read(struct file *file, char __user *to,
+			     size_t count, loff_t *ppos)
+{
+	loff_t pos = *ppos;
+	int ret;
+
+	if (!count)
+		return 0;
+
+	ret = lrng_raw_extract_user(to, count);
+	if (ret < 0)
+		return ret;
+
+	count -= ret;
+	*ppos = pos + count;
+
+	return ret;
+}
+
+static const struct file_operations lrng_raw_name_fops = {
+	.owner = THIS_MODULE,
+	.read = lrng_raw_read,
+};
+
+static int __init lrng_raw_init(void)
+{
+	struct dentry *lrng_raw_debugfs_root;
+
+	lrng_raw_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL);
+	debugfs_create_file_unsafe("lrng_raw", 0400, lrng_raw_debugfs_root,
+				   NULL, &lrng_raw_name_fops);
+
+	return 0;
+}
+
+module_init(lrng_raw_init);
-- 
2.24.1





^ permalink raw reply related	[flat|nested] 162+ messages in thread

* [PATCH v29 12/12] LRNG - add power-on and runtime self-tests
  2020-01-19 21:12         ` [PATCH v29 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
                             ` (10 preceding siblings ...)
  2020-01-19 21:19           ` [PATCH v29 11/12] LRNG - add interface for gathering of raw entropy Stephan Müller
@ 2020-01-19 21:20           ` Stephan Müller
  11 siblings, 0 replies; 162+ messages in thread
From: Stephan Müller @ 2020-01-19 21:20 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greg Kroah-Hartman, linux-crypto, LKML, linux-api,
	Eric W. Biederman, Alexander E. Patrakov, Ahmed S. Darwish,
	Theodore Y. Ts'o, Willy Tarreau, Matthew Garrett,
	Vito Caputo, Andreas Dilger, Jan Kara, Ray Strode,
	William Jon McCann, zhangjs, Andy Lutomirski, Florian Weimer,
	Lennart Poettering, Nicolai Stange, Peter, Matthias,
	Marcelo Henrique Cerri, Roman Drahtmueller, Neil Horman,
	Randy Dunlap, Julia Lawall, Dan Carpenter

Parts of the LRNG are already covered by self-tests, including:

* Self-test of SP800-90A DRBG provided by the Linux kernel crypto API.

* Self-test of the PRNG provided by the Linux kernel crypto API.

* Raw noise source data testing including SP800-90B compliant
  tests when enabling CONFIG_LRNG_HEALTH_TESTS

This patch adds the self-tests for the remaining critical functions of
the LRNG that are essential to maintain entropy and provide
cryptographic strong random numbers. The following self-tests are
implemented:

* Self-test of the time array maintenance. This test verifies whether
the time stamp array management to store multiple values in one integer
implements a concatenation of the data.

* Self-test of the LFSR operation. This test injects a monotonic
increasing counter into the LFSR. After completion of the injection of
the counter, 3 pool words are compared with known good values. The known
good values are calculated with the newly-developed tool
lfsr_testvector_generation provided as part of the LRNG test tool set at
[1].

* Self-test of the Hash_DF operation ensures that this function operates
compliant to the specification. The self-test performs a Hash_DF
operation of a zeroized entropy pool state. The test vectors are
generated using the newly-developed tool hash_df_testvector_generation
provided as part of the LRNG test tool set at [1].

* Self-test of the ChaCha20 DRNG is based on the self-tests that are
already present and implemented with the stand-alone user space
ChaCha20 DRNG implementation available at [2]. The self-tests cover
different use cases of the DRNG seeded with known seed data.

The status of the LRNG self-tests is provided with the selftest_status
SysFS file. If the file contains a zero, the self-tests passed. The
value 0xffffffff means that the self-tests were not executed. Any other
value indicates a self-test failure.

The self-test may be compiled to panic the system if the self-test
fails.

All self-tests operate on private state data structures. This implies
that none of the self-tests have any impact on the regular LRNG
operations. This allows the self-tests to be repeated at runtime by
writing anything into the selftest_status SysFS file.

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

CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
CC: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
CC: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 drivers/char/lrng/Kconfig         |  25 ++
 drivers/char/lrng/Makefile        |   1 +
 drivers/char/lrng/lrng_selftest.c | 418 ++++++++++++++++++++++++++++++
 3 files changed, 444 insertions(+)
 create mode 100644 drivers/char/lrng/lrng_selftest.c

diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig
index 014ee82df79a..896726138651 100644
--- a/drivers/char/lrng/Kconfig
+++ b/drivers/char/lrng/Kconfig
@@ -178,4 +178,29 @@ config LRNG_TESTING
 
 	  If unsure, say N.
 
+config LRNG_SELFTEST
+	bool "Enable power-on and on-demand self-tests"
+	help
+	  The power-on self-tests are executed during boot time
+	  covering the ChaCha20 DRNG, the LFSR processing and the
+	  time stamp management of the LRNG.
+
+	  The on-demand self-tests are triggered by writing any
+	  value into the SysFS file selftest_status. At the same
+	  time, when reading this file, the test status is
+	  returned. A zero indicates that all tests were executed
+	  successfully.
+
+	  If unsure, say Y.
+
+if LRNG_SELFTEST
+
+config LRNG_SELFTEST_PANIC
+	bool "Panic the kernel upon self-test failure"
+	help
+	  If the option is enabled, the kernel is terminated if an
+	  LRNG power-on self-test failure is detected.
+
+endif # LRNG_SELFTEST
+
 endif # LRNG
diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile
index b2ce1979dc4b..92219c565f66 100644
--- a/drivers/char/lrng/Makefile
+++ b/drivers/char/lrng/Makefile
@@ -16,3 +16,4 @@ obj-$(CONFIG_LRNG_KCAPI)	+= lrng_kcapi.o
 obj-$(CONFIG_LRNG_JENT)		+= lrng_jent.o
 obj-$(CONFIG_LRNG_HEALTH_TESTS)	+= lrng_health.o
 obj-$(CONFIG_LRNG_TESTING)	+= lrng_testing.o
+obj-$(CONFIG_LRNG_SELFTEST)	+= lrng_selftest.o
diff --git a/drivers/char/lrng/lrng_selftest.c b/drivers/char/lrng/lrng_selftest.c
new file mode 100644
index 000000000000..bf69ba6bffa1
--- /dev/null
+++ b/drivers/char/lrng/lrng_selftest.c
@@ -0,0 +1,418 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * LRNG power-on and on-demand self-test
+ *
+ * Copyright (C) 2016 - 2020, Stephan Mueller <smueller@chronox.de>
+ */
+
+/*
+ * In addition to the self-tests below, the following LRNG components
+ * are covered with self-tests during regular operation:
+ *
+ * * power-on self-test: SP800-90A DRBG provided by the Linux kernel crypto API
+ * * power-on self-test: PRNG provided by the Linux kernel crypto API
+ * * runtime test: Raw noise source data testing including SP800-90B compliant
+ *		   tests when enabling CONFIG_LRNG_HEALTH_TESTS
+ *
+ * Additional developer tests present with LRNG code:
+ * * SP800-90B APT and RCT test enforcement validation when enabling
+ *   CONFIG_LRNG_APT_BROKEN or CONFIG_LRNG_RCT_BROKEN.
+ * * Collection of raw entropy from the interrupt noise source when enabling
+ *   CONFIG_LRNG_TESTING and pulling the data from the kernel with the provided
+ *   interface.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/lrng.h>
+#include <linux/slab.h>
+
+#include "lrng_chacha20.h"
+#include "lrng_internal.h"
+#include "lrng_lfsr.h"
+#include "lrng_sw_noise.h"
+
+#define LRNG_SELFTEST_PASSED		0
+#define LRNG_SEFLTEST_ERROR_TIME	(1 << 0)
+#define LRNG_SEFLTEST_ERROR_LFSR	(1 << 1)
+#define LRNG_SEFLTEST_ERROR_CHACHA20	(1 << 2)
+#define LRNG_SEFLTEST_ERROR_HASHDF	(1 << 3)
+#define LRNG_SELFTEST_NOT_EXECUTED	0xffffffff
+
+static u32 lrng_time_selftest[LRNG_TIME_ARRAY_SIZE];
+
+static unsigned int lrng_selftest_status = LRNG_SELFTEST_NOT_EXECUTED;
+
+static inline void lrng_time_process_selftest_insert(u32 time)
+{
+	static u32 lrng_time_selftest_ptr = 0;
+	u32 ptr = lrng_time_selftest_ptr++ & LRNG_TIME_WORD_MASK;
+
+	lrng_time_selftest[lrng_time_idx2array(ptr)] |=
+		lrng_time_slot_val(time & LRNG_TIME_SLOTSIZE_MASK,
+				   lrng_time_idx2slot(ptr));
+}
+
+static unsigned int lrng_time_process_selftest(void)
+{
+	u32 time;
+	u32 idx_zero_compare = (0 << 0) | (1 << 8) | (2 << 16) | (3 << 24);
+	u32 idx_one_compare  = (4 << 0) | (5 << 8) | (6 << 16) | (7 << 24);
+	u32 idx_last_compare = ((LRNG_TIME_NUM_VALUES - 4) << 0)  |
+			       ((LRNG_TIME_NUM_VALUES - 3) << 8)  |
+			       ((LRNG_TIME_NUM_VALUES - 2) << 16) |
+			       ((LRNG_TIME_NUM_VALUES - 1) << 24);
+
+	(void)idx_one_compare;
+
+	for (time = 0; time < LRNG_TIME_NUM_VALUES; time++)
+		lrng_time_process_selftest_insert(time);
+
+	if ((lrng_time_selftest[0] != idx_zero_compare) ||
+#if (LRNG_TIME_ARRAY_SIZE > 1)
+	    (lrng_time_selftest[1] != idx_one_compare)  ||
+#endif
+	    (lrng_time_selftest[LRNG_TIME_ARRAY_SIZE - 1] != idx_last_compare))
+	{
+		pr_err("LRNG time array self-test FAILED\n");
+		return LRNG_SEFLTEST_ERROR_TIME;
+	}
+
+	return LRNG_SELFTEST_PASSED;
+}
+
+/*
+ * The test vectors are generated with the lfsr_testvector_generation tool
+ * provided as part of the test tool set of the LRNG.
+ */
+static unsigned int lrng_pool_lfsr_selftest(void)
+{
+	/*
+	 * First, 67th and last entry of entropy pool.
+	 *
+	 * The 67th entry is picked because this one is the first to receive
+	 * an entry. As we start with 1 to inject into the LFSR, the
+	 * 67th entry should be equal to rol(1, 7) >> 3 considering that
+	 * all other values of the LFSR are zero and the the twist value of 0
+	 * is applied.
+	 */
+	static u32 const lrng_lfsr_selftest_result[][3] = {
+		{ 0xf56df24a, 0x00000010, 0x0e014939 },
+		{ 0x4b130726, 0x00000010, 0x2802f509 },
+		{ 0x87279152, 0x00000010, 0x00150000 },
+		{ 0x0b67f997, 0x00000010, 0x00150000 },
+		{ 0x4fea174f, 0x00000010, 0xcbf4a6ae },
+		{ 0x77149108, 0x00000010, 0x77bfadf2 },
+		{ 0x1e96037e, 0x00000010, 0x18017e79 },
+		{ 0xc84acef2, 0x00000010, 0x6345f7a8 },
+		{ 0x6a2eb6df, 0x00000010, 0x03950000 },
+	};
+	struct lrng_pool *lrng_pool, *lrng_pool_aligned;
+	u32 i, ret = LRNG_SELFTEST_PASSED;
+
+	BUILD_BUG_ON(ARRAY_SIZE(lrng_lfsr_selftest_result) <
+							CONFIG_LRNG_POOL_SIZE);
+
+	lrng_pool = kzalloc(sizeof(struct lrng_pool) + LRNG_KCAPI_ALIGN,
+			    GFP_KERNEL);
+	if (!lrng_pool)
+		return LRNG_SEFLTEST_ERROR_LFSR;
+	lrng_pool_aligned = PTR_ALIGN(lrng_pool, sizeof(u32));
+
+	for (i = 1; i <= LRNG_POOL_SIZE; i++)
+		_lrng_pool_lfsr_u32(lrng_pool_aligned, i);
+
+	if ((atomic_read_u32(&lrng_pool_aligned->pool[0]) !=
+	     lrng_lfsr_selftest_result[CONFIG_LRNG_POOL_SIZE][0]) ||
+	    (atomic_read_u32(&lrng_pool_aligned->pool[67 &
+						      (LRNG_POOL_SIZE - 1)]) !=
+	     lrng_lfsr_selftest_result[CONFIG_LRNG_POOL_SIZE][1]) ||
+	    (atomic_read_u32(&lrng_pool_aligned->pool[LRNG_POOL_SIZE - 1]) !=
+	     lrng_lfsr_selftest_result[CONFIG_LRNG_POOL_SIZE][2])) {
+		pr_err("LRNG LFSR self-test FAILED\n");
+		ret = LRNG_SEFLTEST_ERROR_LFSR;
+	}
+
+	kfree(lrng_pool);
+	return ret;
+}
+
+/*
+ * The test vectors are generated with the hash_df_testvector_generation tool
+ * provided as part of the test tool set of the LRNG.
+ */
+static unsigned int lrng_hash_df_selftest(void)
+{
+	const struct lrng_crypto_cb *crypto_cb = &lrng_cc20_crypto_cb;
+
+	/*
+	 * The size of 45 bytes is chosen arbitrarily. Yet, this size should
+	 * ensure that we have at least two hash blocks plus some fraction
+	 * of a hash block generated.
+	 */
+	static u8 const lrng_hash_df_selftest_result[][45] = {
+		{
+			0x3b, 0xbe, 0x7a, 0xbd, 0x2b, 0x16, 0x02, 0x4c,
+			0xfc, 0xd3, 0x02, 0x15, 0xf0, 0x86, 0xd4, 0xdb,
+			0x49, 0xec, 0x26, 0x53, 0xd6, 0xc9, 0x6d, 0xad,
+			0x24, 0xca, 0x72, 0x89, 0x2c, 0xfa, 0x48, 0x18,
+			0xf7, 0x47, 0xb5, 0x2f, 0x92, 0xa2, 0x1b, 0xd9,
+			0x24, 0xa7, 0x2f, 0xa2, 0x0b,
+		}, {
+			0xd2, 0xaa, 0xf9, 0x76, 0x26, 0xc6, 0x13, 0xea,
+			0xb8, 0xde, 0xe6, 0x88, 0x8f, 0xc4, 0x7a, 0x7d,
+			0x9c, 0xb4, 0x1b, 0xd1, 0xd1, 0x8a, 0x40, 0xc9,
+			0xaa, 0x45, 0xa6, 0xb6, 0xb5, 0x6f, 0xf6, 0xbc,
+			0xbb, 0x77, 0x37, 0xbc, 0x5a, 0x2d, 0xcc, 0x84,
+			0x25, 0x68, 0x5e, 0xba, 0x16,
+		}, {
+			0x58, 0x66, 0x82, 0x88, 0x29, 0x19, 0xa4, 0xbb,
+			0x33, 0x42, 0xc9, 0x72, 0x0d, 0x68, 0x6e, 0xb9,
+			0xc6, 0xe0, 0x7a, 0xf9, 0x20, 0xca, 0x6d, 0x18,
+			0x35, 0xec, 0xfa, 0x9e, 0xf6, 0x3a, 0xa7, 0xb6,
+			0x92, 0x7a, 0xe5, 0xcd, 0xc5, 0x13, 0x9f, 0x65,
+			0x6a, 0xe1, 0xe4, 0x3f, 0xb9,
+		}, {
+			0xdd, 0xf1, 0x34, 0xca, 0x08, 0xe3, 0xce, 0x8a,
+			0x26, 0x6b, 0xce, 0x99, 0x8a, 0x84, 0xd2, 0x21,
+			0x98, 0x10, 0x95, 0x5f, 0x9f, 0xc3, 0xf2, 0xe4,
+			0x79, 0x75, 0xb5, 0x15, 0xa7, 0xa2, 0xf1, 0xc4,
+			0xdc, 0x67, 0xcb, 0x67, 0x8c, 0xb2, 0x1b, 0xd5,
+			0xd6, 0x8b, 0xc2, 0x34, 0xd6,
+		}, {
+			0xc3, 0x16, 0x9d, 0xf0, 0x78, 0x15, 0xab, 0xf2,
+			0x2f, 0xc9, 0x2e, 0xe1, 0xc6, 0x5e, 0xfa, 0x03,
+			0xaf, 0xd4, 0xd5, 0x47, 0x2a, 0xe8, 0x06, 0xe8,
+			0x7e, 0x0a, 0x71, 0xc7, 0x0d, 0x39, 0xb1, 0xa9,
+			0x5a, 0x49, 0xee, 0x8b, 0x2f, 0xcd, 0xea, 0x96,
+			0xcc, 0x08, 0x71, 0xef, 0x9c,
+		}, {
+			0x1a, 0x3d, 0x70, 0x39, 0xc2, 0x02, 0x4d, 0x3a,
+			0xaa, 0x14, 0x20, 0x88, 0x96, 0x4c, 0x7c, 0xe4,
+			0xaa, 0x49, 0x89, 0x30, 0x50, 0x96, 0xb6, 0xa7,
+			0x55, 0x0a, 0xf8, 0xd2, 0x4e, 0x83, 0x9d, 0x1f,
+			0x56, 0x49, 0x13, 0xc6, 0x46, 0x55, 0x73, 0x0d,
+			0x74, 0xcd, 0x81, 0xe0, 0x65,
+		}, {
+			0x4b, 0xf6, 0x49, 0x89, 0x2a, 0x9f, 0x67, 0xd7,
+			0xb8, 0x1d, 0xbb, 0x5d, 0xf0, 0x1b, 0x60, 0xb6,
+			0xb7, 0xf3, 0x86, 0x6d, 0xe0, 0x04, 0xa1, 0xbc,
+			0x3b, 0xb0, 0x10, 0x91, 0xe8, 0x22, 0x67, 0x5b,
+			0xe8, 0xf0, 0x4f, 0x82, 0x70, 0xc7, 0xe1, 0xc8,
+			0xd8, 0xad, 0x70, 0xcf, 0xf6,
+		}, {
+			0x60, 0x1f, 0x71, 0x07, 0x92, 0xae, 0xa0, 0x24,
+			0xb6, 0xa4, 0x10, 0x70, 0x1f, 0x94, 0x51, 0x9a,
+			0x5a, 0x81, 0xc4, 0x46, 0x78, 0x56, 0x71, 0xdd,
+			0x45, 0x63, 0x01, 0x34, 0x87, 0x79, 0xb4, 0xd5,
+			0x91, 0x79, 0xb9, 0x93, 0x11, 0x44, 0x50, 0xad,
+			0x64, 0x7e, 0x5c, 0xec, 0x16,
+		}, {
+			0x49, 0x2f, 0xa0, 0x45, 0xf8, 0xb0, 0x80, 0x88,
+			0x79, 0xeb, 0xb6, 0x82, 0x1c, 0xf3, 0x67, 0xc4,
+			0x88, 0x88, 0xe9, 0x75, 0x20, 0x54, 0x78, 0xc6,
+			0x5c, 0x59, 0xcf, 0xd9, 0x73, 0x12, 0x17, 0xf4,
+			0x30, 0x9c, 0xb7, 0x21, 0x45, 0xe2, 0xb6, 0x0c,
+			0x0c, 0xeb, 0x1b, 0xdc, 0xdc,
+		}
+	};
+	struct lrng_pool *lrng_pool, *lrng_pool_aligned;
+	u8 hash_df[sizeof(lrng_hash_df_selftest_result[0])]
+							__aligned(sizeof(u32));
+	u32 generated;
+	int ret = 0;
+
+	BUILD_BUG_ON(ARRAY_SIZE(lrng_hash_df_selftest_result) <
+							CONFIG_LRNG_POOL_SIZE);
+
+	lrng_pool = kzalloc(sizeof(struct lrng_pool) + LRNG_KCAPI_ALIGN,
+			    GFP_KERNEL);
+	if (!lrng_pool)
+		return LRNG_SEFLTEST_ERROR_HASHDF;
+	lrng_pool_aligned = PTR_ALIGN(lrng_pool, sizeof(u32));
+
+	generated = __lrng_pool_hash_df(crypto_cb, NULL, lrng_pool_aligned,
+					hash_df, sizeof(hash_df) << 3);
+
+	if ((generated >> 3) != sizeof(hash_df) ||
+	    memcmp(hash_df, lrng_hash_df_selftest_result[CONFIG_LRNG_POOL_SIZE],
+		   sizeof(hash_df))) {
+		pr_err("LRNG Hash DF self-test FAILED\n");
+		ret = LRNG_SEFLTEST_ERROR_HASHDF;
+	}
+
+	kfree(lrng_pool);
+	return ret;
+}
+
+/*
+ * The test vectors were generated using the ChaCha20 DRNG from
+ * https://www.chronox.de/chacha20.html
+ */
+static unsigned int lrng_chacha20_drng_selftest(void)
+{
+	const struct lrng_crypto_cb *crypto_cb = &lrng_cc20_crypto_cb;
+	static u8 const seed[CHACHA_KEY_SIZE * 2] = {
+		0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+		0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+		0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+		0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+		0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+		0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+		0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+		0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+	};
+	struct chacha20_block chacha20;
+	int ret;
+	u8 outbuf[CHACHA_KEY_SIZE * 2] __aligned(sizeof(u32));
+
+	/*
+	 * Expected result when ChaCha20 DRNG state is zero:
+	 *	* constants are set to "expand 32-byte k"
+	 *	* remaining state is 0
+	 * and pulling one half ChaCha20 DRNG block.
+	 */
+	static u8 const expected_halfblock[CHACHA_KEY_SIZE] = {
+		0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
+		0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
+		0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
+		0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7 };
+
+	/*
+	 * Expected result when ChaCha20 DRNG state is zero:
+	 *	* constants are set to "expand 32-byte k"
+	 *	* remaining state is 0
+	 * followed by a reseed with two keyblocks
+	 *	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+	 *	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+	 *	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+	 *	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+	 *	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+	 *	0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+	 *	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+	 *	0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f
+	 * and pulling one ChaCha20 DRNG block.
+	 */
+	static u8 const expected_oneblock[CHACHA_KEY_SIZE * 2] = {
+		0xf5, 0xb4, 0xb6, 0x5a, 0xec, 0xcd, 0x5a, 0x65,
+		0x87, 0x56, 0xe3, 0x86, 0x51, 0x54, 0xfc, 0x90,
+		0x56, 0xff, 0x5e, 0xae, 0x58, 0xf2, 0x01, 0x88,
+		0xb1, 0x7e, 0xb8, 0x2e, 0x17, 0x9a, 0x27, 0xe6,
+		0x86, 0xb3, 0xed, 0x33, 0xf7, 0xb9, 0x06, 0x05,
+		0x8a, 0x2d, 0x1a, 0x93, 0xc9, 0x0b, 0x80, 0x04,
+		0x03, 0xaa, 0x60, 0xaf, 0xd5, 0x36, 0x40, 0x11,
+		0x67, 0x89, 0xb1, 0x66, 0xd5, 0x88, 0x62, 0x6d };
+
+	/*
+	 * Expected result when ChaCha20 DRNG state is zero:
+	 *	* constants are set to "expand 32-byte k"
+	 *	* remaining state is 0
+	 * followed by a reseed with one key block plus one byte
+	 *	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+	 *	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+	 *	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+	 *	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+	 *	0x20
+	 * and pulling less than one ChaCha20 DRNG block.
+	 */
+	static u8 const expected_block_nonalinged[CHACHA_KEY_SIZE + 1] = {
+		0x3d, 0x13, 0x47, 0x1e, 0x7f, 0x7c, 0x99, 0x33,
+		0xfc, 0x44, 0xa4, 0xdd, 0xf9, 0x3d, 0xe1, 0x9a,
+		0xd4, 0xe8, 0x7a, 0x7d, 0x42, 0xac, 0xd1, 0xcd,
+		0x10, 0x69, 0xe7, 0xbf, 0xd4, 0xfd, 0x69, 0x4b,
+		0xa7 };
+
+	memset(&chacha20, 0, sizeof(chacha20));
+	lrng_cc20_init_rfc7539(&chacha20);
+
+	/* Generate with zero state */
+	ret = crypto_cb->lrng_drng_generate_helper(&chacha20, outbuf,
+						   sizeof(expected_halfblock));
+	if (ret != sizeof(expected_halfblock))
+		goto err;
+	if (memcmp(outbuf, expected_halfblock, sizeof(expected_halfblock)))
+		goto err;
+
+	/* Clear state of DRNG */
+	memset(&chacha20.key.u[0], 0, 48);
+
+	/* Reseed with 2 key blocks */
+	ret = crypto_cb->lrng_drng_seed_helper(&chacha20, seed,
+					       sizeof(expected_oneblock));
+	if (ret < 0)
+		goto err;
+	ret = crypto_cb->lrng_drng_generate_helper(&chacha20, outbuf,
+						   sizeof(expected_oneblock));
+	if (ret != sizeof(expected_oneblock))
+		goto err;
+	if (memcmp(outbuf, expected_oneblock, sizeof(expected_oneblock)))
+		goto err;
+
+	/* Clear state of DRNG */
+	memset(&chacha20.key.u[0], 0, 48);
+
+	/* Reseed with 1 key block and one byte */
+	ret = crypto_cb->lrng_drng_seed_helper(&chacha20, seed,
+					sizeof(expected_block_nonalinged));
+	if (ret < 0)
+		goto err;
+	ret = crypto_cb->lrng_drng_generate_helper(&chacha20, outbuf,
+					sizeof(expected_block_nonalinged));
+	if (ret != sizeof(expected_block_nonalinged))
+		goto err;
+	if (memcmp(outbuf, expected_block_nonalinged,
+		   sizeof(expected_block_nonalinged)))
+		goto err;
+
+	return LRNG_SELFTEST_PASSED;
+
+err:
+	pr_err("LRNG ChaCha20 DRNG self-test FAILED\n");
+	return LRNG_SEFLTEST_ERROR_CHACHA20;
+}
+
+static int lrng_selftest(void)
+{
+	unsigned int ret = lrng_time_process_selftest();
+
+	ret |= lrng_pool_lfsr_selftest();
+	ret |= lrng_chacha20_drng_selftest();
+	ret |= lrng_hash_df_selftest();
+
+	if (ret) {
+		if (IS_ENABLED(CONFIG_LRNG_SELFTEST_PANIC))
+			panic("LRNG self-tests failed: %u\n", ret);
+	} else {
+		pr_info("LRNG self-tests passed\n");
+	}
+
+	lrng_selftest_status = ret;
+
+	if (lrng_selftest_status)
+		return -EFAULT;
+	return 0;
+}
+
+#ifdef CONFIG_SYSFS
+/* Re-perform self-test when any value is written to the sysfs file. */
+static int lrng_selftest_sysfs_set(const char *val,
+				   const struct kernel_param *kp)
+{
+	return lrng_selftest();
+}
+
+static const struct kernel_param_ops lrng_selftest_sysfs = {
+	.set = lrng_selftest_sysfs_set,
+	.get = param_get_uint,
+};
+module_param_cb(selftest_status, &lrng_selftest_sysfs, &lrng_selftest_status,
+		0644);
+#endif	/* CONFIG_SYSFS */
+
+static int __init lrng_selftest_init(void)
+{
+	return lrng_selftest();
+}
+
+module_init(lrng_selftest_init);
-- 
2.24.1





^ permalink raw reply related	[flat|nested] 162+ messages in thread

end of thread, other threads:[~2020-01-20  7:02 UTC | newest]

Thread overview: 162+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-11-11 18:17 [PATCH v24 00/12] /dev/random - a new approach with full SP800-90B compliance Stephan Müller
2019-11-11 18:18 ` [PATCH v24 01/12] Linux Random Number Generator Stephan Müller
2019-11-11 23:54   ` Thomas Gleixner
2019-11-12  2:25     ` Stephan Müller
2019-11-12 10:16       ` Thomas Gleixner
2019-11-12 22:30   ` kbuild test robot
2019-11-12 23:15     ` Stephan Müller
2019-11-13  0:14   ` kbuild test robot
2019-11-13  0:25     ` Stephan Müller
2019-11-24  4:51   ` Sandy Harris
2019-11-24  9:02     ` Stephan Mueller
2019-11-11 18:19 ` [PATCH v24 02/12] LRNG - allocate one SDRNG instance per NUMA node Stephan Müller
2019-11-11 18:20 ` [PATCH v24 03/12] LRNG - /proc interface Stephan Müller
2019-11-11 18:20 ` [PATCH v24 04/12] LRNG - add switchable DRNG support Stephan Müller
2019-11-11 18:21 ` [PATCH v24 05/12] crypto: DRBG - externalize DRBG functions for LRNG Stephan Müller
2019-11-11 18:21 ` [PATCH v24 06/12] LRNG - add SP800-90A DRBG extension Stephan Müller
2019-11-11 18:22 ` [PATCH v24 07/12] LRNG - add kernel crypto API PRNG extension Stephan Müller
2019-11-11 18:23 ` [PATCH v24 08/12] crypto: provide access to a static Jitter RNG state Stephan Müller
2019-11-11 18:23 ` [PATCH v24 09/12] LRNG - add Jitter RNG fast noise source Stephan Müller
2019-11-11 18:24 ` [PATCH v24 10/12] LRNG - add TRNG support Stephan Müller
2019-11-11 18:26 ` [PATCH v24 11/12] LRNG - add SP800-90B compliant health tests Stephan Müller
2019-11-12 19:58   ` Alexander E. Patrakov
2019-11-12 23:11     ` Stephan Müller
2019-11-13  0:36     ` Stephan Müller
2019-11-13  6:02       ` Alexander E. Patrakov
2019-11-14  1:46         ` Stephan Müller
2019-11-11 18:26 ` [PATCH v24 12/12] LRNG - add interface for gathering of raw entropy Stephan Müller
2019-11-12 20:55   ` kbuild test robot
2019-11-12 23:13     ` Stephan Müller
2019-11-12 13:23 ` [PATCH v24 00/12] /dev/random - a new approach with full SP800-90B compliance Florian Weimer
2019-11-12 22:43   ` Stephan Müller
2019-11-12 15:33 ` Andy Lutomirski
2019-11-12 23:03   ` Stephan Müller
2019-11-12 23:26     ` Stephan Müller
2019-11-13  4:24   ` Stephan Müller
2019-11-13  4:48     ` Andy Lutomirski
2019-11-13 12:16       ` Stephan Müller
2019-11-16  9:32 ` [PATCH v25 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
2019-11-16  9:33   ` [PATCH v25 01/12] Linux Random Number Generator Stephan Müller
2019-11-16 11:25     ` Thomas Gleixner
2019-11-17 10:30       ` Stephan Müller
2019-11-16 18:13     ` Nicolai Stange
2019-11-17 11:01       ` Stephan Müller
2019-11-16  9:33   ` [PATCH v25 02/12] LRNG - allocate one SDRNG instance per NUMA node Stephan Müller
2019-11-16  9:34   ` [PATCH v25 03/12] LRNG - /proc interface Stephan Müller
2019-11-16 16:39     ` Andy Lutomirski
2019-11-17 12:16       ` Stephan Müller
2019-11-19 10:06         ` Andy Lutomirski
2019-11-19 10:55           ` Stephan Mueller
2019-11-19 17:40             ` Andy Lutomirski
2019-11-16 23:36     ` Eric W. Biederman
2019-11-17 11:37       ` Stephan Müller
2019-11-16  9:34   ` [PATCH v25 04/12] LRNG - add switchable DRNG support Stephan Müller
2019-11-16  9:35   ` [PATCH v25 05/12] crypto: DRBG - externalize DRBG functions for LRNG Stephan Müller
2019-11-16  9:35   ` [PATCH v25 06/12] LRNG - add SP800-90A DRBG extension Stephan Müller
2019-11-16  9:35   ` [PATCH v25 07/12] LRNG - add kernel crypto API PRNG extension Stephan Müller
2019-11-16  9:36   ` [PATCH v25 08/12] crypto: provide access to a static Jitter RNG state Stephan Müller
2019-11-16  9:36   ` [PATCH v25 09/12] LRNG - add Jitter RNG fast noise source Stephan Müller
2019-11-20 13:33     ` Neil Horman
2019-11-20 20:07       ` Stephan Müller
2019-11-21 14:19         ` Neil Horman
2019-11-21 14:33           ` Stephan Mueller
2019-11-16  9:37   ` [PATCH v25 10/12] LRNG - add TRNG support Stephan Müller
2019-11-16 16:09     ` Andy Lutomirski
2019-11-17 11:10       ` Stephan Müller
2019-11-19 10:07         ` Andy Lutomirski
2019-11-19 10:46           ` Stephan Mueller
2019-11-19 12:41           ` Greg Kroah-Hartman
2019-11-20  8:58             ` Stephan Müller
2019-11-20  9:55               ` Alexander E. Patrakov
2019-11-20 13:29               ` Greg Kroah-Hartman
2019-11-20 19:51                 ` Stephan Müller
2019-11-20 19:57                   ` Alexander E. Patrakov
2019-11-20 20:32                   ` Greg Kroah-Hartman
2019-11-21 13:06                     ` Stephan Müller
2019-11-16  9:37   ` [PATCH v25 11/12] LRNG - add SP800-90B compliant health tests Stephan Müller
2019-11-16  9:38   ` [PATCH v25 12/12] LRNG - add interface for gathering of raw entropy Stephan Müller
2019-11-16 16:51     ` Andy Lutomirski
2019-11-17 22:55       ` Stephan Müller
2019-11-19 10:04         ` Andy Lutomirski
2019-11-19 17:17     ` Randy Dunlap
2019-11-20  9:01       ` Stephan Müller
2019-11-21 12:18     ` Nicolai Stange
2019-11-21 15:18       ` Stephan Müller
2019-11-23 20:08   ` [PATCH v26 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
2019-11-23 20:10     ` [PATCH v26 01/12] Linux Random Number Generator Stephan Müller
2019-11-24 22:44       ` kbuild test robot
2019-11-25  6:29         ` Stephan Mueller
2019-11-23 20:10     ` [PATCH v26 02/12] LRNG - allocate one SDRNG instance per NUMA node Stephan Müller
2019-11-23 20:11     ` [PATCH v26 03/12] LRNG - sysctls and /proc interface Stephan Müller
2019-11-23 20:11     ` [PATCH v26 04/12] LRNG - add switchable DRNG support Stephan Müller
2019-11-23 20:31     ` [PATCH v26 05/12] crypto: DRBG - externalize DRBG functions for LRNG Stephan Müller
2019-11-23 20:32     ` [PATCH v26 06/12] LRNG - add SP800-90A DRBG extension Stephan Müller
2019-11-23 20:32     ` [PATCH v26 07/12] LRNG - add kernel crypto API PRNG extension Stephan Müller
2019-11-23 20:33     ` [PATCH v26 08/12] crypto: provide access to a static Jitter RNG state Stephan Müller
2019-11-23 20:34     ` [PATCH v26 09/12] LRNG - add Jitter RNG fast noise source Stephan Müller
2019-11-23 20:34     ` [PATCH v26 10/12] LRNG - add TRNG support Stephan Müller
2019-11-23 20:34     ` [PATCH v26 11/12] LRNG - add SP800-90B compliant health tests Stephan Müller
2019-11-23 20:35     ` [PATCH v26 12/12] LRNG - add interface for gathering of raw entropy Stephan Müller
2020-01-09  8:29     ` [PATCH v27 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
2020-01-09  8:30       ` [PATCH v27 01/12] Linux Random Number Generator Stephan Müller
2020-01-16  6:09         ` kbuild test robot
2020-01-16  6:41           ` Stephan Mueller
2020-01-09  8:31       ` [PATCH v27 02/12] LRNG - allocate one DRNG instance per NUMA node Stephan Müller
2020-01-09  8:31       ` [PATCH v27 03/12] LRNG - sysctls and /proc interface Stephan Müller
2020-01-09  8:32       ` [PATCH v27 04/12] LRNG - add switchable DRNG support Stephan Müller
2020-01-11  7:09         ` kbuild test robot
2020-01-12 10:12           ` Stephan Müller
2020-01-09  8:32       ` [PATCH v27 05/12] crypto: DRBG - externalize DRBG functions for LRNG Stephan Müller
2020-01-09  8:32       ` [PATCH v27 06/12] LRNG - add SP800-90A DRBG extension Stephan Müller
2020-01-09  8:33       ` [PATCH v27 07/12] LRNG - add kernel crypto API PRNG extension Stephan Müller
2020-01-09  8:33       ` [PATCH v27 08/12] crypto: provide access to a static Jitter RNG state Stephan Müller
2020-01-09  8:34       ` [PATCH v27 09/12] LRNG - add Jitter RNG fast noise source Stephan Müller
2020-01-10  0:24         ` Randy Dunlap
2020-01-10  7:45           ` Stephan Mueller
2020-01-09  8:34       ` [PATCH v27 10/12] LRNG - add SP800-90B compliant health tests Stephan Müller
2020-01-10  0:20         ` Randy Dunlap
2020-01-10  8:27           ` Stephan Mueller
2020-01-09  8:35       ` [PATCH v27 11/12] LRNG - add interface for gathering of raw entropy Stephan Müller
2020-01-09  8:35       ` [PATCH v27 12/12] LRNG - add power-on and runtime self-tests Stephan Müller
2020-01-10  0:22         ` Randy Dunlap
2020-01-10  7:48           ` Stephan Mueller
2020-01-13 10:39         ` Dan Carpenter
2020-01-13 10:46           ` Stephan Mueller
2020-01-15 10:31       ` [PATCH v28 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
2020-01-15 10:31         ` [PATCH v28 01/12] Linux Random Number Generator Stephan Müller
2020-01-16  0:11           ` Randy Dunlap
2020-01-16  7:22             ` Stephan Mueller
2020-01-15 10:32         ` [PATCH v28 02/12] LRNG - allocate one DRNG instance per NUMA node Stephan Müller
2020-01-15 10:32         ` [PATCH v28 03/12] LRNG - sysctls and /proc interface Stephan Müller
2020-01-15 10:32         ` [PATCH v28 04/12] LRNG - add switchable DRNG support Stephan Müller
2020-01-15 10:33         ` [PATCH v28 05/12] crypto: DRBG - externalize DRBG functions for LRNG Stephan Müller
2020-01-15 10:33         ` [PATCH v28 06/12] LRNG - add SP800-90A DRBG extension Stephan Müller
2020-01-16  0:14           ` Randy Dunlap
2020-01-16  6:55             ` Stephan Mueller
2020-01-15 10:34         ` [PATCH v28 07/12] LRNG - add kernel crypto API PRNG extension Stephan Müller
2020-01-16  0:15           ` Randy Dunlap
2020-01-16  6:54             ` Stephan Mueller
2020-01-15 10:34         ` [PATCH v28 08/12] crypto: provide access to a static Jitter RNG state Stephan Müller
2020-01-15 10:34         ` [PATCH v28 09/12] LRNG - add Jitter RNG fast noise source Stephan Müller
2020-01-16  0:17           ` Randy Dunlap
2020-01-16  6:51             ` Stephan Mueller
2020-01-15 10:35         ` [PATCH v28 10/12] LRNG - add SP800-90B compliant health tests Stephan Müller
2020-01-15 10:35         ` [PATCH v28 11/12] LRNG - add interface for gathering of raw entropy Stephan Müller
2020-01-16  0:18           ` Randy Dunlap
2020-01-16  6:43             ` Stephan Mueller
2020-01-16  6:48               ` Randy Dunlap
2020-01-16  6:52                 ` Stephan Mueller
2020-01-15 10:36         ` [PATCH v28 12/12] LRNG - add power-on and runtime self-tests Stephan Müller
2020-01-19 21:12         ` [PATCH v29 00/12] /dev/random - a new approach with full SP800-90B Stephan Müller
2020-01-19 21:13           ` [PATCH v29 01/12] Linux Random Number Generator Stephan Müller
2020-01-19 21:13           ` [PATCH v29 02/12] LRNG - allocate one DRNG instance per NUMA node Stephan Müller
2020-01-19 21:14           ` [PATCH v29 03/12] LRNG - sysctls and /proc interface Stephan Müller
2020-01-19 21:14           ` [PATCH v29 04/12] LRNG - add switchable DRNG support Stephan Müller
2020-01-19 21:15           ` [PATCH v29 05/12] crypto: DRBG - externalize DRBG functions for LRNG Stephan Müller
2020-01-19 21:16           ` [PATCH v29 06/12] LRNG - add SP800-90A DRBG extension Stephan Müller
2020-01-19 21:16           ` [PATCH v29 07/12] LRNG - add kernel crypto API PRNG extension Stephan Müller
2020-01-19 21:17           ` [PATCH v29 08/12] crypto: provide access to a static Jitter RNG state Stephan Müller
2020-01-19 21:18           ` [PATCH v29 09/12] LRNG - add Jitter RNG fast noise source Stephan Müller
2020-01-19 21:18           ` [PATCH v29 10/12] LRNG - add SP800-90B compliant health tests Stephan Müller
2020-01-19 21:19           ` [PATCH v29 11/12] LRNG - add interface for gathering of raw entropy Stephan Müller
2020-01-19 21:20           ` [PATCH v29 12/12] LRNG - add power-on and runtime self-tests Stephan Müller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).