Skip to contentSkip to conversation

/dev/random - a new approach with full SP800-90B compliance

PATCH Superseded Stephan Müller 14 participants 162 messages Nov 11, 2019 – Jan 19, 2020 Page 1 of 2

Subsystems (3)

v24 of 43 Superseded Latest is v43 →

lore
Share & tools
lore
#0 lore raw

v24 cover /dev/random - a new approach with full SP800-90B compliance

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" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>

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
Signature · 1 line
2.23.0
#1 lore raw

PATCH v24 1/12 Linux Random Number Generator

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" <[email protected]>
CC: "Alexander E. Patrakov" <[email protected]>
CC: "Ahmed S. Darwish" <[email protected]>
CC: "Theodore Y. Ts'o" <[email protected]>
CC: Willy Tarreau <[email protected]>
CC: Matthew Garrett <[email protected]>
CC: Vito Caputo <[email protected]>
CC: Andreas Dilger <[email protected]>
CC: Jan Kara <[email protected]>
CC: Ray Strode <[email protected]>
CC: William Jon McCann <[email protected]>
CC: zhangjs <[email protected]>
CC: Andy Lutomirski <[email protected]>
CC: Florian Weimer <[email protected]>
CC: Lennart Poettering <[email protected]>
CC: Nicolai Stange <[email protected]>
Mathematical aspects Reviewed-by: "Peter, Matthias" <[email protected]>

---
 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
MAINTAINERS +7 -0
index cba1095547fd..7232989d3a1c 100644
@@ -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 <[email protected]>
+S:	Maintained
+W:	https://www.chronox.de/lrng.html
+F:	drivers/char/lrng/*
+F:	include/linux/lrng.h
+
 LIS3LV02D ACCELEROMETER DRIVER
 M:	Eric Piel <[email protected]>
 S:	Maintained
drivers/char/Kconfig +2 -0
index df0fc997dc3e..cebb3a62c2ca 100644
@@ -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
drivers/char/Makefile +8 -1
index 7c5ea6f9df14..46ede09fd6d3 100644
@@ -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
drivers/char/lrng/Kconfig new file +55 -0

55 lines not on this page · raw message

drivers/char/lrng/Makefile new file +9 -0
new file mode 100644
index 000000000000..2761623715d2
@@ -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 \
drivers/char/lrng/lrng_archrandom.c new file +105 -0

105 lines not on this page · raw message

drivers/char/lrng/lrng_aux.c new file +161 -0

161 lines not on this page · raw message

drivers/char/lrng/lrng_chacha20.c new file +341 -0

341 lines not on this page · raw message

drivers/char/lrng/lrng_interfaces.c new file +649 -0

649 lines not on this page · raw message

drivers/char/lrng/lrng_internal.h new file +313 -0

313 lines not on this page · raw message

drivers/char/lrng/lrng_pool.c new file +673 -0

673 lines not on this page · raw message

drivers/char/lrng/lrng_sdrng.c new file +458 -0

458 lines not on this page · raw message

drivers/char/lrng/lrng_sw_noise.c new file +156 -0

156 lines not on this page · raw message

include/linux/lrng.h new file +83 -0

44 lines not on this page · raw message

The rest of this diff is not shown. View the raw message.

Signature · 1 line
2.23.0

Part of the diff is not shown here. View the raw message.

#2 lore raw

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

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

Quoted 9 lines
drivers/char/lrng/lrng_archrandom.c new file +8 -0
@@ -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 <[email protected]>
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES

drivers/char/lrng/lrng_archrandom.c line 18

Quoted 10 lines
drivers/char/lrng/lrng_archrandom.c new file +10 -0
+ * 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

#3 lore raw

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

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

Hi Thomas,

Quoted 6 lines

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.

Quoted 27 lines

While skimming through the patches I noticed, that you thankfully added the SPDX license identifiers, but

Quoted 9 lines
drivers/char/lrng/lrng_archrandom.c new file +8 -0
@@ -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 <[email protected]>
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES

drivers/char/lrng/lrng_archrandom.c line 18

Quoted 10 lines
drivers/char/lrng/lrng_archrandom.c new file +10 -0
+ * 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.

Quoted 7 lines

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

#4 lore raw

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

Quoted 4 lines · Stephan Müller

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

Quoted 1 line

Can you please get rid of those?

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

Appreciated.

Quoted 2 lines

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

Of course!

#5 lore raw

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

In reply to Stephan Müller
Thank you for the patch! Yet something to improve:

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

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/[email protected] Intel Corporation

#6 lore raw

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

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

Hi kbuild,

Quoted 22 lines

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
Quoted 10 lines

If you fix the issue, kindly add following tag

All errors (new ones prefixed by >>):

In file included from <command-line>:0:0:

include/linux/lrng.h: In function 'lrng_set_drng_cb':

Quoted 2 lines
Quoted 2 lines

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.

Quoted 15 lines
    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

Quoted 2 lines

80 lrng_set_drng_cb(const struct lrng_crypto_cb *cb) { return
-EOPNOTSUPP; }

Quoted 7 lines
    81	#endif	/* CONFIG_LRNG_DRNG_SWITCH */
    82

---
0-DAY kernel test infrastructure Open Source Technology
Center https://lists.01.org/hyperkitty/list/[email protected] Intel Corporation

Ciao
Stephan

#7 lore raw

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

In reply to Stephan Müller
Thank you for the patch! Yet something to improve:

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

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/[email protected] Intel Corporation

#8 lore raw

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

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

Hi kbuild,

Quoted 25 lines

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
Quoted 6 lines

If you fix the issue, kindly add following tag

All errors (new ones prefixed by >>):

drivers/char/lrng/lrng_sw_noise.c: In function

'add_interrupt_randomness':

Quoted 8 lines
Quoted 2 lines
Quoted 2 lines

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));
                          ^~~~~~
Quoted 3 lines
Quoted 3 lines

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]

Quoted 6 lines
       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.

Quoted 13 lines
   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;
Quoted 8 lines
   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);

Quoted 2 lines
Quoted 2 lines

145 size_t n = (sizeof(struct pt_regs) /

sizeof(u32));

Quoted 9 lines
   146
Quoted 1 line

147 ip = instruction_pointer(regs);

---
0-DAY kernel test infrastructure Open Source Technology
Center https://lists.01.org/hyperkitty/list/[email protected] Intel Corporation

Ciao
Stephan

#9 lore raw

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

In reply to Stephan Müller
Quoted 2 lines · Stephan Müller

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:

Quoted 7 lines

(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?

Quoted 2 lines

The LRNG allows the TRNG and secondary DRNG mechanism to be changed at runtime.

Why? This strikes me as pointless complication.

Quoted 6 lines

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

Quoted 1 line

* lockless LFSR to collect raw entropy

This too.

#10 lore raw

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

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

Hi Sandy,

Quoted 13 lines
Quoted 2 lines · Stephan Müller

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:

Quoted 4 lines

(a) When an interrupt occurs, the high-resolution time stamp is mixed

into the LFSR. ...

Quoted 7 lines
Quoted 5 lines

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

Quoted 5 lines
Quoted 3 lines

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.

Quoted 8 lines
Quoted 7 lines

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

Quoted 7 lines

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.

Quoted 1 line

* 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

#11 lore raw

PATCH v24 2/12 LRNG - allocate one SDRNG instance per NUMA node

In reply to Stephan Müller

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" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>
---
 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
drivers/char/lrng/Makefile +2 -0
index 2761623715d2..a00cddb45773 100644
@@ -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
drivers/char/lrng/lrng_internal.h +5 -0
index 242f9b5b4f3d..e6ac2c527378 100644
@@ -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 **************************/
 
drivers/char/lrng/lrng_numa.c new file +114 -0

114 lines not on this page · raw message

Signature · 1 line
2.23.0
#12 lore raw

PATCH v24 3/12 LRNG - /proc interface

In reply to Stephan Müller

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" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>
---
 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
drivers/char/lrng/Makefile +1 -0
index a00cddb45773..b6240b73e33d 100644
@@ -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
drivers/char/lrng/lrng_interfaces.c +0 -1
index e652849a1bdb..1c9517c6df4a 100644
@@ -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? */
drivers/char/lrng/lrng_internal.h +4 -0
index e6ac2c527378..8528c2e8de88 100644
@@ -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 *******************************/
 
drivers/char/lrng/lrng_proc.c new file +192 -0

192 lines not on this page · raw message

Signature · 1 line
2.23.0
#13 lore raw

PATCH v24 4/12 LRNG - add switchable DRNG support

In reply to Stephan Müller

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" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>
---
 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
drivers/char/lrng/Kconfig +7 -0
index edf8be6aa0b1..a468d8292bac 100644
@@ -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
drivers/char/lrng/Makefile +1 -0
index b6240b73e33d..6bac97638767 100644
@@ -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
drivers/char/lrng/lrng_switch.c new file +198 -0

198 lines not on this page · raw message

Signature · 1 line
2.23.0
#14 lore raw

PATCH v24 5/12 crypto: DRBG - externalize DRBG functions for LRNG

In reply to Stephan Müller

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

CC "Eric W. Biederman" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>
---
 crypto/drbg.c         | 16 ++++++++++------
 include/crypto/drbg.h |  7 +++++++
 2 files changed, 17 insertions(+), 6 deletions(-)
crypto/drbg.c +10 -6
index b6929eb5f565..5561dd0f09e1 100644
@@ -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)
 {
include/crypto/drbg.h +7 -0
index 8c9af21efce1..c63b20375235 100644
@@ -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 */
Signature · 1 line
2.23.0
#15 lore raw

PATCH v24 6/12 LRNG - add SP800-90A DRBG extension

In reply to Stephan Müller

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" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>
---
 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
drivers/char/lrng/Kconfig +11 -0
index a468d8292bac..bf61e730e50f 100644
@@ -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
drivers/char/lrng/Makefile +1 -0
index 6bac97638767..e3a704b3466c 100644
@@ -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
drivers/char/lrng/lrng_drbg.c new file +274 -0

274 lines not on this page · raw message

Signature · 1 line
2.23.0
#16 lore raw

PATCH v24 7/12 LRNG - add kernel crypto API PRNG extension

In reply to Stephan Müller

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" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>
---
 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
drivers/char/lrng/Kconfig +10 -0
index bf61e730e50f..eb1cd63433dc 100644
@@ -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
drivers/char/lrng/Makefile +1 -0
index e3a704b3466c..027b6ea51c20 100644
@@ -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
drivers/char/lrng/lrng_kcapi.c new file +341 -0

341 lines not on this page · raw message

Signature · 1 line
2.23.0
#17 lore raw

PATCH v24 8/12 crypto: provide access to a static Jitter RNG state

In reply to Stephan Müller

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" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>
---
 crypto/jitterentropy.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)
crypto/jitterentropy.c +23 -0
index 77fa2120fe0c..3a815495f778 100644
@@ -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;
+}
Signature · 1 line
2.23.0
#18 lore raw

PATCH v24 9/12 LRNG - add Jitter RNG fast noise source

In reply to Stephan Müller

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" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>
---
 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
drivers/char/lrng/Kconfig +11 -0
index eb1cd63433dc..c6d26b88cdac 100644
@@ -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
drivers/char/lrng/Makefile +1 -0
index 027b6ea51c20..a87d800c9aae 100644
@@ -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
drivers/char/lrng/lrng_jent.c new file +101 -0

101 lines not on this page · raw message

Signature · 1 line
2.23.0
#19 lore raw

PATCH v24 10/12 LRNG - add TRNG support

In reply to Stephan Müller

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" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>
---
 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
drivers/char/lrng/Kconfig +22 -0
index c6d26b88cdac..efc5f9aaa2a3 100644
@@ -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
drivers/char/lrng/Makefile +1 -0
index a87d800c9aae..1c72bc060bce 100644
@@ -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
drivers/char/lrng/lrng_trng.c new file +301 -0

301 lines not on this page · raw message

Signature · 1 line
2.23.0
#20 lore raw

PATCH v24 11/12 LRNG - add SP800-90B compliant health tests

In reply to 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.

- 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" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>
---
 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
drivers/char/lrng/Kconfig +13 -0
index efc5f9aaa2a3..4373a1a19538 100644
@@ -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
drivers/char/lrng/Makefile +1 -0
index 1c72bc060bce..0713e9c0aa6e 100644
@@ -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
drivers/char/lrng/lrng_health.c new file +424 -0

424 lines not on this page · raw message

Signature · 1 line
2.23.0
#21 lore raw

Re: [PATCH v24 11/12] LRNG - add SP800-90B compliant health tests

11.11.2019 23:26, Stephan Müller пишет:

Quoted 7 lines

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?

Quoted 14 lines

- 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.

Quoted 2 lines

- 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.

Quoted 105 lines

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" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>
---
  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

drivers/char/lrng/Kconfig +0 -0
index efc5f9aaa2a3..4373a1a19538 100644
@@ -113,4 +113,17 @@ config LRNG_TRNG_SUPPORT
  	  With the TRNG support the /dev/random device will block
  	  if insufficient entropy is available.
 

drivers/char/lrng/Kconfig config LRNG_TRNG_SUPPORT · line 125

Quoted 10 lines
drivers/char/lrng/Kconfig +10 -0
+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?

Quoted 444 lines
drivers/char/lrng/Kconfig +3 -0
+
+	  If unsure, say Y.
+
  endif # LRNG
drivers/char/lrng/Makefile +1 -0
index 1c72bc060bce..0713e9c0aa6e 100644
@@ -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
drivers/char/lrng/lrng_health.c new file +424 -0
new file mode 100644
index 000000000000..b8d96cec1f71
@@ -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 <[email protected]>
+ *
+ * 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;
+}
Signature · 1 line
Alexander E. Patrakov
#22 lore raw

Re: [PATCH v24 11/12] LRNG - add SP800-90B compliant health tests

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

Hi Alexander,

Quoted 11 lines

11.11.2019 23:26, Stephan Müller пишет:

Quoted 8 lines

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.

Quoted 15 lines
Quoted 15 lines

- 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.

Quoted 5 lines
Quoted 3 lines

- 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.
"""

Quoted 112 lines
Quoted 112 lines

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" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>

---

  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

drivers/char/lrng/Kconfig +0 -0
index efc5f9aaa2a3..4373a1a19538 100644
@@ -113,4 +113,17 @@ config LRNG_TRNG_SUPPORT
 
  	  With the TRNG support the /dev/random device will block
  	  if insufficient entropy is available.
 
Quoted 14 lines

drivers/char/lrng/Kconfig config LRNG_TRNG_SUPPORT · line 125

Quoted 10 lines
drivers/char/lrng/Kconfig +10 -0
+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.

Quoted 447 lines
Quoted 447 lines
drivers/char/lrng/Kconfig +3 -0
+
+	  If unsure, say Y.
+

endif # LRNG

drivers/char/lrng/Makefile +1 -0
index 1c72bc060bce..0713e9c0aa6e 100644
@@ -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
(quoted diff) +0 -0

b/drivers/char/lrng/lrng_health.c new file mode 100644 index 000000000000..b8d96cec1f71

drivers/char/lrng/lrng_health.c new file +65 -0
@@ -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 <[email protected]>
+ *
+ * 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 +

\

drivers/char/lrng/lrng_health.c new file +36 -0
+					 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.
+
*************************************************************************
**/ +

drivers/char/lrng/lrng_health.c new file +25 -0
+/**
+ * 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) +{

drivers/char/lrng/lrng_health.c new file +19 -0
+	/* 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) +{

drivers/char/lrng/lrng_health.c new file +39 -0
+	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. +
*************************************************************************
**/ +

drivers/char/lrng/lrng_health.c new file +29 -0
+/**
+ * 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
+ */

drivers/char/lrng/lrng_health.c new file +32 -0
+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.
+
*************************************************************************
**/ +

drivers/char/lrng/lrng_health.c new file +46 -0
+/**
+ * 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. +
*************************************************************************
**/ +

drivers/char/lrng/lrng_health.c new file +18 -0
+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) +{

drivers/char/lrng/lrng_health.c new file +15 -0
+	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
+
*************************************************************************
**/ +

drivers/char/lrng/lrng_health.c new file +16 -0
+/**
+ * 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
+ */

drivers/char/lrng/lrng_health.c new file +13 -0
+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);
Quoted 8 lines

drivers/char/lrng/lrng_health.c line 424

Quoted 8 lines
drivers/char/lrng/lrng_health.c new file +8 -0
+	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

#23 lore raw

Re: [PATCH v24 11/12] LRNG - add SP800-90B compliant health tests

In reply to Alexander E. Patrakov

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

Hi Alexander,

Quoted 6 lines
Quoted 6 lines
drivers/char/lrng/Kconfig +6 -0
+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
Quoted 8 lines

drivers/char/lrng/Kconfig config LRNG_TRNG_SUPPORT · line 125

Quoted 4 lines
drivers/char/lrng/Kconfig +4 -0
+	  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

#24 lore raw

Re: [PATCH v24 11/12] LRNG - add SP800-90B compliant health tests

ср, 13 нояб. 2019 г. в 05:38, Stephan Müller <[email protected]>:

Quoted 21 lines

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

Hi Alexander,

Quoted 11 lines

drivers/char/lrng/Kconfig config LRNG_TRNG_SUPPORT · line 125

Quoted 10 lines
drivers/char/lrng/Kconfig +10 -0
+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.
Quoted 3 lines

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?

Quoted 4 lines

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

#25 lore raw

Re: [PATCH v24 11/12] LRNG - add SP800-90B compliant health tests

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

Hi Alexander,

Quoted 34 lines

ср, 13 нояб. 2019 г. в 05:38, Stephan Müller <[email protected]>:

Quoted 16 lines

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

Hi Alexander,

Quoted 11 lines
Quoted 10 lines
drivers/char/lrng/Kconfig +10 -0
+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.
Quoted 8 lines
Quoted 3 lines

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

Quoted 5 lines

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.

Quoted 3 lines

--
Alexander E. Patrakov

Ciao
Stephan

#26 lore raw

PATCH v24 12/12 LRNG - add interface for gathering of raw entropy

In reply to Stephan Müller

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" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>
---
 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
drivers/char/lrng/Kconfig +16 -0
index 4373a1a19538..c3d7524b7698 100644
@@ -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
drivers/char/lrng/Makefile +1 -0
index 0713e9c0aa6e..c0b6cc4301fe 100644
@@ -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
drivers/char/lrng/lrng_testing.c new file +324 -0

324 lines not on this page · raw message

Signature · 1 line
2.23.0
#27 lore raw

Re: [PATCH v24 12/12] LRNG - add interface for gathering of raw entropy

Thank you for the patch! Perhaps something to improve:

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

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/[email protected] Intel Corporation

#28 lore raw

Re: [PATCH v24 12/12] LRNG - add interface for gathering of raw entropy

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

Hi kbuild,

Quoted 38 lines

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

All warnings (new ones prefixed by >>):

drivers/char/lrng/lrng_testing.c: In function 'lrng_raw_extract_user':

Quoted 2 lines
Quoted 2 lines

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

Quoted 8 lines
   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.

Quoted 35 lines
   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;
Quoted 8 lines
Quoted 1 line

237 }

   238

---
0-DAY kernel test infrastructure Open Source Technology
Center https://lists.01.org/hyperkitty/list/[email protected] Intel Corporation

Ciao
Stephan

#29 lore raw
In reply to Stephan Müller

* Stephan Müller:

Quoted 3 lines

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

#30 lore raw

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

Hi Florian,

Quoted 10 lines

* Stephan Müller:

Quoted 4 lines

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

Quoted 7 lines

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

#31 lore raw
In reply to Stephan Müller
Quoted 9 lines · Stephan Müller

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!

Quoted 9 lines

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

#32 lore raw

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

Hi Andy,

Quoted 18 lines · Stephan Müller
Quoted 8 lines

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!

Quoted 6 lines

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.

Quoted 8 lines
Quoted 3 lines

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.

Quoted 6 lines

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

Quoted 6 lines

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

Quoted 5 lines

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.

Quoted 6 lines

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.

Quoted 3 lines

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.

Quoted 3 lines

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.

Quoted 3 lines

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

#33 lore raw

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

Hi Stephan,

Quoted 5 lines

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

Hi Andy,

Quoted 1 line

On Mon, Nov 11, 2019 at 11:13 AM Stephan Müller <[email protected]>

Quoted 122 lines · wrote:
Quoted 20 lines
Quoted 10 lines

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!

Quoted 7 lines

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.

Quoted 8 lines
Quoted 3 lines

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.

Quoted 11 lines

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.

Quoted 5 lines

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.

Quoted 5 lines

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.

Quoted 2 lines

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.

Quoted 3 lines

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.

Quoted 2 lines

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.

Quoted 7 lines

[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

Quoted 3 lines

Ciao
Stephan

Ciao
Stephan

#34 lore raw
In reply to Andy Lutomirski

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

Hi Andy,

Quoted 49 lines · Stephan Müller
Quoted 8 lines

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!

Quoted 9 lines

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.

Quoted 4 lines

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

#35 lore raw
Quoted 59 lines · Stephan Müller

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

Hi Andy,

Quoted 49 lines · Stephan Müller
Quoted 8 lines

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!

Quoted 9 lines

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.

Quoted 4 lines

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.

Quoted 4 lines

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.

Quoted 4 lines

- 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?

Quoted 9 lines

- 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.

Quoted 8 lines

- 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.

Quoted 8 lines

- 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.

Quoted 4 lines

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

#36 lore raw

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

Hi Andy,

Quoted 9 lines
Quoted 8 lines

- 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.

Quoted 4 lines

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.

Quoted 11 lines
Quoted 8 lines

- 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.

Quoted 22 lines
Quoted 9 lines

- 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.

Quoted 4 lines

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.

Quoted 18 lines
Quoted 10 lines

- 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.

Quoted 4 lines

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.

Quoted 4 lines

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.

Quoted 2 lines

--Andy

Ciao
Stephan

#37 lore raw

v25 cover /dev/random - a new approach with full SP800-90B

In reply to Stephan Müller

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" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>

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
Signature · 1 line
2.23.0
#38 lore raw

PATCH v25 1/12 Linux Random Number Generator

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" <[email protected]>
CC: "Alexander E. Patrakov" <[email protected]>
CC: "Ahmed S. Darwish" <[email protected]>
CC: "Theodore Y. Ts'o" <[email protected]>
CC: Willy Tarreau <[email protected]>
CC: Matthew Garrett <[email protected]>
CC: Vito Caputo <[email protected]>
CC: Andreas Dilger <[email protected]>
CC: Jan Kara <[email protected]>
CC: Ray Strode <[email protected]>
CC: William Jon McCann <[email protected]>
CC: zhangjs <[email protected]>
CC: Andy Lutomirski <[email protected]>
CC: Florian Weimer <[email protected]>
CC: Lennart Poettering <[email protected]>
CC: Nicolai Stange <[email protected]>
Mathematical aspects Reviewed-by: "Peter, Matthias" <[email protected]>

---
 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
MAINTAINERS +7 -0
index cba1095547fd..7232989d3a1c 100644
@@ -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 <[email protected]>
+S:	Maintained
+W:	https://www.chronox.de/lrng.html
+F:	drivers/char/lrng/*
+F:	include/linux/lrng.h
+
 LIS3LV02D ACCELEROMETER DRIVER
 M:	Eric Piel <[email protected]>
 S:	Maintained
drivers/char/Kconfig +2 -0
index df0fc997dc3e..cebb3a62c2ca 100644
@@ -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
drivers/char/Makefile +8 -1
index 7c5ea6f9df14..46ede09fd6d3 100644
@@ -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
drivers/char/lrng/Kconfig new file +55 -0

55 lines not on this page · raw message

drivers/char/lrng/Makefile new file +9 -0
new file mode 100644
index 000000000000..2761623715d2
@@ -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 \
drivers/char/lrng/lrng_archrandom.c new file +92 -0

92 lines not on this page · raw message

drivers/char/lrng/lrng_aux.c new file +148 -0

148 lines not on this page · raw message

drivers/char/lrng/lrng_chacha20.c new file +328 -0

328 lines not on this page · raw message

drivers/char/lrng/lrng_interfaces.c new file +648 -0

648 lines not on this page · raw message

drivers/char/lrng/lrng_internal.h new file +300 -0

300 lines not on this page · raw message

drivers/char/lrng/lrng_pool.c new file +660 -0

660 lines not on this page · raw message

drivers/char/lrng/lrng_sdrng.c new file +436 -0

436 lines not on this page · raw message

drivers/char/lrng/lrng_sw_noise.c new file +144 -0

144 lines not on this page · raw message

include/linux/lrng.h new file +83 -0

83 lines not on this page · raw message

Signature · 1 line
2.23.0
#39 lore raw

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

Quoted 19 lines · Stephan Müller
drivers/char/lrng/lrng_sw_noise.c new file +19 -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);

drivers/char/lrng/lrng_sw_noise.c line 142

Quoted 10 lines
drivers/char/lrng/lrng_sw_noise.c new file +10 -0
+			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

#40 lore raw

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

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

Hi Thomas,

Quoted 25 lines · Stephan Müller
Quoted 24 lines
drivers/char/lrng/lrng_sw_noise.c new file +24 -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
Quoted 8 lines

drivers/char/lrng/lrng_sw_noise.c line 142

Quoted 5 lines
drivers/char/lrng/lrng_sw_noise.c new file +5 -0
+			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

#41 lore raw

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

In reply to Stephan Müller

Hi Stephan,

Quoted 1 line · Stephan Müller

+/* 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, ...

Quoted 17 lines
drivers/char/lrng/lrng_sdrng.c new file +17 -0
+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

drivers/char/lrng/lrng_sdrng.c line 364

Quoted 10 lines
drivers/char/lrng/lrng_sdrng.c new file +10 -0
+		 * 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

Quoted 21 lines
drivers/char/lrng/lrng_sdrng.c new file +21 -0
+	}
+
+	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 */
Signature · 2 lines
SUSE Software Solutions Germany GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg), GF: Felix Imendörffer
#42 lore raw

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

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

Hi Nicolai,

Quoted 70 lines

Hi Stephan,

Quoted 1 line · Stephan Müller

+/* 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, ...

Quoted 17 lines
drivers/char/lrng/lrng_sdrng.c new file +17 -0
+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

drivers/char/lrng/lrng_sdrng.c line 364

Quoted 10 lines
drivers/char/lrng/lrng_sdrng.c new file +10 -0
+		 * 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().

Quoted 8 lines

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 -

Quoted 1 line

kernel_init_freeable -> do_basic_setup -> do_initcalls where the initcalls

registered with the core_initcall callback are now executed as the first batch.

Quoted 8 lines

Thanks,

Nicolai

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

Thank you, added.

Quoted 14 lines
Quoted 14 lines
drivers/char/lrng/lrng_sdrng.c new file +13 -0
+	}
+
+	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.
+	 */
Quoted 8 lines

drivers/char/lrng/lrng_sdrng.c line 385

Quoted 8 lines
drivers/char/lrng/lrng_sdrng.c new file +8 -0
+	lrng_sdrng_unlock(&lrng_sdrng_atomic, &flags);
+
+	lrng_trng_init();
+
+	lrng_set_available();
+}
+
+/* Reset LRNG such that all existing entropy is gone */

Ciao
Stephan

#43 lore raw

PATCH v25 2/12 LRNG - allocate one SDRNG instance per NUMA node

In reply to Stephan Müller

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" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>
---
 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
drivers/char/lrng/Makefile +2 -0
index 2761623715d2..a00cddb45773 100644
@@ -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
drivers/char/lrng/lrng_internal.h +5 -0
index a3d9e0bce884..e1f9b6b166fd 100644
@@ -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 **************************/
 
drivers/char/lrng/lrng_numa.c new file +101 -0

101 lines not on this page · raw message

Signature · 1 line
2.23.0
#44 lore raw

PATCH v25 3/12 LRNG - /proc interface

In reply to Stephan Müller

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" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>
---
 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
drivers/char/lrng/Makefile +1 -0
index a00cddb45773..b6240b73e33d 100644
@@ -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
drivers/char/lrng/lrng_interfaces.c +0 -1
index 5d6af10aba81..c90b24239565 100644
@@ -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? */
drivers/char/lrng/lrng_internal.h +4 -0
index e1f9b6b166fd..9ace72f9cc21 100644
@@ -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 *******************************/
 
drivers/char/lrng/lrng_proc.c new file +179 -0

179 lines not on this page · raw message

Signature · 1 line
2.23.0
#45 lore raw

Re: [PATCH v25 03/12] LRNG - /proc interface

Quoted 6 lines · Stephan Müller

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?

#46 lore raw

Re: [PATCH v25 03/12] LRNG - /proc interface

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

Hi Andy,

Quoted 7 lines
Quoted 5 lines · Stephan Müller

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

#47 lore raw

Re: [PATCH v25 03/12] LRNG - /proc interface

Quoted 13 lines · Stephan Müller

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

Hi Andy,

Quoted 7 lines
Quoted 5 lines · Stephan Müller

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?

Quoted 7 lines

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.

#48 lore raw

Re: [PATCH v25 03/12] LRNG - /proc interface

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

Hi Andy,

Quoted 17 lines · Stephan Müller
Quoted 16 lines

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

Hi Andy,

Quoted 8 lines
Quoted 6 lines

On Nov 16, 2019, at 1:40 AM, Stephan Müller <[email protected]> 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?

Quoted 7 lines
Quoted 4 lines

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.

Quoted 2 lines

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

#49 lore raw

Re: [PATCH v25 03/12] LRNG - /proc interface

Quoted 27 lines · Stephan Mueller

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

Hi Andy,

Quoted 22 lines · Stephan Müller
Quoted 20 lines

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

Hi Andy,

Quoted 8 lines
Quoted 6 lines

On Nov 16, 2019, at 1:40 AM, Stephan Müller <[email protected]> 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.

Quoted 7 lines
Quoted 2 lines

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.

#50 lore raw

Re: [PATCH v25 03/12] LRNG - /proc interface

In reply to Stephan Müller
Quoted 3 lines · Stephan Müller

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.

Eric

Quoted 4 lines
drivers/char/lrng/lrng_proc.c new file +4 -0
+
+extern struct ctl_table random_table[];
+struct ctl_table random_table[] = {
+	{
#51 lore raw

Re: [PATCH v25 03/12] LRNG - /proc interface

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

Hi Eric,

Quoted 8 lines
Quoted 3 lines · Stephan Müller

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.

Quoted 5 lines

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.

Quoted 6 lines

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.

Quoted 5 lines

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.

Quoted 5 lines

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.

Quoted 8 lines

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.

Quoted 6 lines

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.

Quoted 8 lines

Eric

drivers/char/lrng/lrng_proc.c line 120

Quoted 4 lines
drivers/char/lrng/lrng_proc.c new file +4 -0
+
+extern struct ctl_table random_table[];
+struct ctl_table random_table[] = {
+	{

Ciao
Stephan

#52 lore raw

PATCH v25 4/12 LRNG - add switchable DRNG support

In reply to Stephan Müller

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" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>
---
 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
drivers/char/lrng/Kconfig +7 -0
index 1ba10fd421f3..c6e8eafd836c 100644
@@ -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
drivers/char/lrng/Makefile +1 -0
index b6240b73e33d..6bac97638767 100644
@@ -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
drivers/char/lrng/lrng_switch.c new file +185 -0

185 lines not on this page · raw message

Signature · 1 line
2.23.0
#53 lore raw

PATCH v25 5/12 crypto: DRBG - externalize DRBG functions for LRNG

In reply to Stephan Müller

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

CC "Eric W. Biederman" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>
---
 crypto/drbg.c         | 16 ++++++++++------
 include/crypto/drbg.h |  7 +++++++
 2 files changed, 17 insertions(+), 6 deletions(-)
crypto/drbg.c +10 -6
index b6929eb5f565..5561dd0f09e1 100644
@@ -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)
 {
include/crypto/drbg.h +7 -0
index 8c9af21efce1..c63b20375235 100644
@@ -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 */
Signature · 1 line
2.23.0
#54 lore raw

PATCH v25 6/12 LRNG - add SP800-90A DRBG extension

In reply to Stephan Müller

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" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>
---
 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
drivers/char/lrng/Kconfig +11 -0
index c6e8eafd836c..dcdf4ef83da5 100644
@@ -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
drivers/char/lrng/Makefile +1 -0
index 6bac97638767..e3a704b3466c 100644
@@ -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
drivers/char/lrng/lrng_drbg.c new file +261 -0

261 lines not on this page · raw message

Signature · 1 line
2.23.0
#55 lore raw

PATCH v25 7/12 LRNG - add kernel crypto API PRNG extension

In reply to Stephan Müller

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" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>
---
 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
drivers/char/lrng/Kconfig +10 -0
index dcdf4ef83da5..03e6e2ec356b 100644
@@ -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
drivers/char/lrng/Makefile +1 -0
index e3a704b3466c..027b6ea51c20 100644
@@ -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
drivers/char/lrng/lrng_kcapi.c new file +328 -0

328 lines not on this page · raw message

Signature · 1 line
2.23.0
#56 lore raw

PATCH v25 8/12 crypto: provide access to a static Jitter RNG state

In reply to Stephan Müller

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" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>
---
 crypto/jitterentropy.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)
crypto/jitterentropy.c +23 -0
index 77fa2120fe0c..3a815495f778 100644
@@ -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;
+}
Signature · 1 line
2.23.0
#57 lore raw

PATCH v25 9/12 LRNG - add Jitter RNG fast noise source

In reply to Stephan Müller

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" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>
---
 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
drivers/char/lrng/Kconfig +11 -0
index 03e6e2ec356b..80fc723c67d2 100644
@@ -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
drivers/char/lrng/Makefile +1 -0
index 027b6ea51c20..a87d800c9aae 100644
@@ -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
drivers/char/lrng/lrng_jent.c new file +88 -0

88 lines not on this page · raw message

Signature · 1 line
2.23.0
#58 lore raw

Re: [PATCH v25 09/12] LRNG - add Jitter RNG fast noise source

Quoted 110 lines · Stephan Müller

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" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>
---
 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
drivers/char/lrng/Kconfig +11 -0
index 03e6e2ec356b..80fc723c67d2 100644
@@ -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
drivers/char/lrng/Makefile +1 -0
index 027b6ea51c20..a87d800c9aae 100644
@@ -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
drivers/char/lrng/lrng_jent.c new file +42 -0
new file mode 100644
index 000000000000..43114a44b8f5
@@ -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 <[email protected]>
+ */
+
+#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;

drivers/char/lrng/lrng_jent.c line 52

Quoted 10 lines
drivers/char/lrng/lrng_jent.c new file +10 -0
+	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

Quoted 42 lines
drivers/char/lrng/lrng_jent.c new file +36 -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);
+}
Signature · 1 line
2.23.0
#59 lore raw

Re: [PATCH v25 09/12] LRNG - add Jitter RNG fast noise source

Am Mittwoch, 20. November 2019, 14:33:03 CET schrieb Neil Horman:

Hi Neil,

Quoted 127 lines · Stephan Müller
Quoted 126 lines

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" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>

---

 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
drivers/char/lrng/Kconfig +11 -0
index 03e6e2ec356b..80fc723c67d2 100644
@@ -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
drivers/char/lrng/Makefile +1 -0
index 027b6ea51c20..a87d800c9aae 100644
@@ -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
drivers/char/lrng/lrng_jent.c new file +13 -0
new file mode 100644
index 000000000000..43114a44b8f5
@@ -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 <[email protected]>
+ */
+
+#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.
+ */

drivers/char/lrng/lrng_jent.c new file +3 -0
+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");

drivers/char/lrng/lrng_jent.c new file +28 -0
+
+/**
+ * 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;
Quoted 8 lines

drivers/char/lrng/lrng_jent.c

Quoted 2 lines
drivers/char/lrng/lrng_jent.c new file +2 -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

#60 lore raw

Re: [PATCH v25 09/12] LRNG - add Jitter RNG fast noise source

Quoted 155 lines · Stephan Müller

Am Mittwoch, 20. November 2019, 14:33:03 CET schrieb Neil Horman:

Hi Neil,

Quoted 127 lines · Stephan Müller
Quoted 126 lines

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" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>

---

 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
drivers/char/lrng/Kconfig +11 -0
index 03e6e2ec356b..80fc723c67d2 100644
@@ -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
drivers/char/lrng/Makefile +1 -0
index 027b6ea51c20..a87d800c9aae 100644
@@ -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
drivers/char/lrng/lrng_jent.c new file +13 -0
new file mode 100644
index 000000000000..43114a44b8f5
@@ -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 <[email protected]>
+ */
+
+#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.
+ */

drivers/char/lrng/lrng_jent.c new file +3 -0
+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");

drivers/char/lrng/lrng_jent.c new file +28 -0
+
+/**
+ * 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;
Quoted 8 lines

drivers/char/lrng/lrng_jent.c

Quoted 2 lines
drivers/char/lrng/lrng_jent.c new file +2 -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.

Quoted 6 lines

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

Quoted 6 lines

Thank you for your review!

Ciao
Stephan

#61 lore raw

Re: [PATCH v25 09/12] LRNG - add Jitter RNG fast noise source

Am Donnerstag, 21. November 2019, 15:19:30 CET schrieb Neil Horman:

Hi Neil,

Quoted 49 lines · Stephan Müller
Quoted 48 lines

Am Mittwoch, 20. November 2019, 14:33:03 CET schrieb Neil Horman:

Hi Neil,

Quoted 44 lines · Stephan Müller
Quoted 43 lines

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" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>

---

 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
drivers/char/lrng/Kconfig +0 -0
index 03e6e2ec356b..80fc723c67d2 100644
@@ -80,4 +80,15 @@ config LRNG_KCAPI
 
 	  provided by the selected kernel crypto API RNG.
 
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines

drivers/char/lrng/Kconfig config LRNG_KCAPI

Quoted 7 lines
drivers/char/lrng/Kconfig +5 -0
 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

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

drivers/char/lrng/Kconfig

Quoted 2 lines
drivers/char/lrng/Kconfig +2 -0
+	  this option enables the use of the Jitter RNG. Its default
+	  entropy level is 16 bits of entropy per 256 data bits 

delivered

Quoted 1 line
Quoted 1 line
Quoted 1 line

drivers/char/lrng/Kconfig

Quoted 1 line
drivers/char/lrng/Kconfig +1 -0
+	  by the Jitter RNG. This entropy level can be changed at 

boot

Quoted 1 line
Quoted 1 line
Quoted 1 line

drivers/char/lrng/Kconfig

Quoted 1 line
drivers/char/lrng/Kconfig +1 -0
+	  time or at runtime with the lrng_base.jitterrng 

configuration

Quoted 111 lines
Quoted 105 lines
Quoted 80 lines
Quoted 69 lines
drivers/char/lrng/Kconfig +2 -0
+	  variable.
+
 
 endif # LRNG
drivers/char/lrng/Makefile +1 -0
index 027b6ea51c20..a87d800c9aae 100644
@@ -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
drivers/char/lrng/lrng_jent.c new file +13 -0
new file mode 100644
index 000000000000..43114a44b8f5
@@ -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 <[email protected]>
+ */
+
+#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.
+ */

drivers/char/lrng/lrng_jent.c new file +3 -0
+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");

drivers/char/lrng/lrng_jent.c new file +7 -0
+
+/**
+ * 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
+ */

drivers/char/lrng/lrng_jent.c new file +11 -0
+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;

drivers/char/lrng/lrng_jent.c line 52

Quoted 10 lines
drivers/char/lrng/lrng_jent.c new file +10 -0
+	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;
+	}
+
Quoted 8 lines

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.

Quoted 5 lines

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?

Quoted 7 lines

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.

Quoted 10 lines

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

Quoted 4 lines

Thank you for your review!

Ciao
Stephan

Ciao
Stephan

#62 lore raw

PATCH v25 10/12 LRNG - add TRNG support

In reply to Stephan Müller

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" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>
---
 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
drivers/char/lrng/Kconfig +22 -0
index 80fc723c67d2..122d67ee110e 100644
@@ -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
drivers/char/lrng/Makefile +1 -0
index a87d800c9aae..1c72bc060bce 100644
@@ -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
drivers/char/lrng/lrng_trng.c new file +283 -0

283 lines not on this page · raw message

Signature · 1 line
2.23.0
#63 lore raw

Re: [PATCH v25 10/12] LRNG - add TRNG support

Quoted 8 lines · Stephan Müller

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

...

Quoted 5 lines

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.

#64 lore raw

Re: [PATCH v25 10/12] LRNG - add TRNG support

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

Hi Andy,

Quoted 21 lines
Quoted 5 lines · Stephan Müller

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

...

Quoted 5 lines

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.

Quoted 3 lines

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

#65 lore raw

Re: [PATCH v25 10/12] LRNG - add TRNG support

Quoted 30 lines · Stephan Müller

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

Hi Andy,

Quoted 21 lines
Quoted 5 lines · Stephan Müller

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

...

Quoted 5 lines

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.

Quoted 3 lines

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.

Quoted 6 lines

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.

Quoted 10 lines

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.

#66 lore raw

Re: [PATCH v25 10/12] LRNG - add TRNG support

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

Hi Andy,

Quoted 39 lines · Stephan Müller
Quoted 38 lines

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

Hi Andy,

Quoted 26 lines
Quoted 7 lines

On Nov 16, 2019, at 1:40 AM, Stephan Müller <[email protected]> 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).

...

Quoted 6 lines

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.

Quoted 4 lines

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.

Quoted 7 lines
Quoted 3 lines

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.

Quoted 7 lines
Quoted 7 lines

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

Quoted 7 lines
Quoted 4 lines
         [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

#67 lore raw

Re: [PATCH v25 10/12] LRNG - add TRNG support

In reply to Andy Lutomirski
Quoted 5 lines · Andy Lutomirski
Quoted 5 lines

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

Quoted 7 lines
Quoted 4 lines
         [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

#68 lore raw

Re: [PATCH v25 10/12] LRNG - add TRNG support

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

Hi Greg,

Quoted 10 lines · Andy Lutomirski
Quoted 9 lines
Quoted 9 lines

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 },
Quoted 7 lines
Quoted 4 lines
Quoted 1 line

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

#69 lore raw

Re: [PATCH v25 10/12] LRNG - add TRNG support

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

Quoted 22 lines

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) &&
Quoted 8 lines
                ((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.

Signature · 1 line
Alexander E. Patrakov
#70 lore raw

Re: [PATCH v25 10/12] LRNG - add TRNG support

In reply to Stephan Müller
Quoted 19 lines · Stephan Müller

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

Hi Greg,

Quoted 15 lines · Andy Lutomirski
Quoted 13 lines
Quoted 10 lines

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.

Quoted 6 lines
Quoted 2 lines

[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

#71 lore raw

Re: [PATCH v25 10/12] LRNG - add TRNG support

Am Mittwoch, 20. November 2019, 14:29:18 CET schrieb Greg Kroah-Hartman:

Hi Greg,

Quoted 31 lines · Stephan Müller
Quoted 20 lines

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

Hi Greg,

Quoted 16 lines · Andy Lutomirski
Quoted 14 lines
Quoted 11 lines

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.

Quoted 6 lines
Quoted 2 lines

[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.

Quoted 6 lines

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

#72 lore raw

Re: [PATCH v25 10/12] LRNG - add TRNG support

21.11.2019 00:51, Stephan Müller пишет:

Quoted 65 lines

Am Mittwoch, 20. November 2019, 14:29:18 CET schrieb Greg Kroah-Hartman:

Hi Greg,

Quoted 31 lines · Stephan Müller
Quoted 20 lines

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

Hi Greg,

Quoted 16 lines · Andy Lutomirski
Quoted 14 lines
Quoted 11 lines

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.

Quoted 6 lines
Quoted 2 lines

[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.

Quoted 6 lines

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?

Quoted 6 lines

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.

Signature · 1 line
Alexander E. Patrakov
#73 lore raw

Re: [PATCH v25 10/12] LRNG - add TRNG support

In reply to Stephan Müller
Quoted 57 lines · Stephan Müller

Am Mittwoch, 20. November 2019, 14:29:18 CET schrieb Greg Kroah-Hartman:

Hi Greg,

Quoted 31 lines · Stephan Müller
Quoted 20 lines

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

Hi Greg,

Quoted 16 lines · Andy Lutomirski
Quoted 14 lines
Quoted 11 lines

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.

Quoted 6 lines
Quoted 2 lines

[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.

Quoted 6 lines

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

Quoted 7 lines

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

#74 lore raw

Re: [PATCH v25 10/12] LRNG - add TRNG support

Am Mittwoch, 20. November 2019, 21:32:32 CET schrieb Greg Kroah-Hartman:

Hi Greg,

Quoted 2 lines

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

#75 lore raw

PATCH v25 11/12 LRNG - add SP800-90B compliant health tests

In reply to 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 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" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>
---
 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
drivers/char/lrng/Kconfig +56 -0
index 122d67ee110e..e6ca3acc1e48 100644
@@ -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
drivers/char/lrng/Makefile +1 -0
index 1c72bc060bce..0713e9c0aa6e 100644
@@ -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
drivers/char/lrng/lrng_health.c new file +409 -0

409 lines not on this page · raw message

Signature · 1 line
2.23.0
#76 lore raw

PATCH v25 12/12 LRNG - add interface for gathering of raw entropy

In reply to Stephan Müller

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" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>
---
 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
drivers/char/lrng/Kconfig +16 -0
index e6ca3acc1e48..4ccc710832ef 100644
@@ -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
drivers/char/lrng/Makefile +1 -0
index 0713e9c0aa6e..c0b6cc4301fe 100644
@@ -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
drivers/char/lrng/lrng_testing.c new file +324 -0

324 lines not on this page · raw message

Signature · 1 line
2.23.0
#77 lore raw

Re: [PATCH v25 12/12] LRNG - add interface for gathering of raw entropy

Quoted 160 lines · Stephan Müller

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" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>

---

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

drivers/char/lrng/Kconfig +16 -0
index e6ca3acc1e48..4ccc710832ef 100644
@@ -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

drivers/char/lrng/Makefile +0 -0
index 0713e9c0aa6e..c0b6cc4301fe 100644
@@ -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

drivers/char/lrng/Makefile +1 -0
+obj-$(CONFIG_LRNG_TESTING)    += lrng_testing.o
drivers/char/lrng/lrng_testing.c new file +72 -0
new file mode 100644
index 000000000000..5c33d3bd2172
@@ -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 <[email protected]>
+ */
+
+#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");
+}
+

drivers/char/lrng/lrng_testing.c line 82

Quoted 10 lines
drivers/char/lrng/lrng_testing.c new file +10 -0
+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?

Quoted 4 lines
drivers/char/lrng/lrng_testing.c new file +4 -0
+
+    /*
+     * Disable entropy testing for boot time testing after ring buffer
+     * is filled.

drivers/char/lrng/lrng_testing.c line 96

Quoted 10 lines
drivers/char/lrng/lrng_testing.c new file +10 -0
+     */
+    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.

drivers/char/lrng/lrng_testing.c line 99

Quoted 3 lines
drivers/char/lrng/lrng_testing.c new file +3 -0
+
+    /* We got at least one event, enable the reader now. */
+    atomic_set(&lrng_rb_first_in, 1);

But not necessarily in position 0.

drivers/char/lrng/lrng_testing.c line 112

Quoted 13 lines
drivers/char/lrng/lrng_testing.c new file +13 -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.

Quoted 37 lines
drivers/char/lrng/lrng_testing.c new file +37 -0
+
+    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.

drivers/char/lrng/lrng_testing.c line 163

Quoted 10 lines
drivers/char/lrng/lrng_testing.c new file +10 -0
+         */
+        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.

#78 lore raw

Re: [PATCH v25 12/12] LRNG - add interface for gathering of raw entropy

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

Hi Andy,

Quoted 163 lines
Quoted 163 lines · Stephan Müller

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" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>

---

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

drivers/char/lrng/Kconfig +16 -0
index e6ca3acc1e48..4ccc710832ef 100644
@@ -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

drivers/char/lrng/Makefile +0 -0
index 0713e9c0aa6e..c0b6cc4301fe 100644
@@ -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

drivers/char/lrng/Makefile +1 -0
+obj-$(CONFIG_LRNG_TESTING)    += lrng_testing.o
(quoted diff) +0 -0

b/drivers/char/lrng/lrng_testing.c new file mode 100644 index 000000000000..5c33d3bd2172

drivers/char/lrng/lrng_testing.c new file +26 -0
@@ -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 <[email protected]>
+ */
+
+#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)

drivers/char/lrng/lrng_testing.c new file +12 -0
+
+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");

drivers/char/lrng/lrng_testing.c new file +36 -0
+
+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;
Quoted 8 lines
Quoted 8 lines
drivers/char/lrng/lrng_testing.c new file +6 -0
+    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;
Quoted 3 lines

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.

Quoted 8 lines
Quoted 8 lines
drivers/char/lrng/lrng_testing.c new file +8 -0
+
+    /*
+     * 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;
Quoted 8 lines

drivers/char/lrng/lrng_testing.c line 96

Quoted 6 lines
drivers/char/lrng/lrng_testing.c new file +6 -0
+    }
+
+    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.

Quoted 6 lines

drivers/char/lrng/lrng_testing.c line 99

Quoted 4 lines
drivers/char/lrng/lrng_testing.c new file +3 -0
+
+    /* 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.

Quoted 17 lines
Quoted 4 lines
drivers/char/lrng/lrng_testing.c new file +3 -0
+
+    if (wq_has_sleeper(&lrng_raw_read_wait))
+        wake_up_interruptible(&lrng_raw_read_wait);

drivers/char/lrng/lrng_testing.c line 112

Quoted 10 lines
drivers/char/lrng/lrng_testing.c new file +10 -0
+
+    /*
+     * 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.

Quoted 5 lines

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.

Quoted 4 lines

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.

Quoted 9 lines

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.

Quoted 3 lines

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.

Quoted 42 lines
Quoted 42 lines
drivers/char/lrng/lrng_testing.c new file +42 -0
+
+    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;
+        }
Quoted 8 lines

drivers/char/lrng/lrng_testing.c line 163

Quoted 5 lines
drivers/char/lrng/lrng_testing.c new file +5 -0
+
+        /* 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

#79 lore raw

Re: [PATCH v25 12/12] LRNG - add interface for gathering of raw entropy

Quoted 212 lines · Stephan Müller

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

Hi Andy,

Quoted 163 lines
Quoted 163 lines · Stephan Müller

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" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>

---

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

drivers/char/lrng/Kconfig +16 -0
index e6ca3acc1e48..4ccc710832ef 100644
@@ -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

drivers/char/lrng/Makefile +0 -0
index 0713e9c0aa6e..c0b6cc4301fe 100644
@@ -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

drivers/char/lrng/Makefile +1 -0
+obj-$(CONFIG_LRNG_TESTING)    += lrng_testing.o
(quoted diff) +0 -0

b/drivers/char/lrng/lrng_testing.c new file mode 100644 index 000000000000..5c33d3bd2172

drivers/char/lrng/lrng_testing.c new file +26 -0
@@ -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 <[email protected]>
+ */
+
+#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)

drivers/char/lrng/lrng_testing.c new file +12 -0
+
+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");

drivers/char/lrng/lrng_testing.c new file +36 -0
+
+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;
Quoted 8 lines
Quoted 8 lines
drivers/char/lrng/lrng_testing.c new file +6 -0
+    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:

Quoted 5 lines
        if (this_cpu_read(cpu_tlbstate.loaded_mm) == &init_mm)
                return;

--
2.17.1

static inline void lrng_time_process(void)

Quoted 40 lines

{
...

        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;
Quoted 3 lines

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.

Quoted 8 lines
Quoted 8 lines
drivers/char/lrng/lrng_testing.c new file +8 -0
+
+    /*
+     * 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;
Quoted 8 lines

drivers/char/lrng/lrng_testing.c line 96

Quoted 6 lines
drivers/char/lrng/lrng_testing.c new file +6 -0
+    }
+
+    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.

Quoted 5 lines

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.

Quoted 3 lines

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 <=.

#80 lore raw

Re: [PATCH v25 12/12] LRNG - add interface for gathering of raw entropy

In reply to Stephan Müller

Hi,

drivers/char/lrng/Kconfig config LRNG_APT_CUTOFF · line 174

Quoted 11 lines · Stephan Müller
drivers/char/lrng/Kconfig +3 -0
index e6ca3acc1e48..4ccc710832ef 100644
@@ -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'.

Quoted 4 lines
drivers/char/lrng/Kconfig +4 -0
+	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

drivers/char/lrng/Kconfig config LRNG_APT_CUTOFF · line 188

Quoted 10 lines
drivers/char/lrng/Kconfig +9 -0
+	  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.

Signature · 1 line
~Randy
#81 lore raw

Re: [PATCH v25 12/12] LRNG - add interface for gathering of raw entropy

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

Hi Randy,

Quoted 12 lines

Hi,

Quoted 9 lines · Stephan Müller
drivers/char/lrng/Kconfig +0 -0
index e6ca3acc1e48..4ccc710832ef 100644
@@ -169,4 +169,20 @@ config LRNG_APT_CUTOFF
 
 	default 325 if !LRNG_APT_BROKEN
 	default 32 if LRNG_APT_BROKEN
 
Quoted 6 lines

drivers/char/lrng/Kconfig config LRNG_APT_CUTOFF · line 174

Quoted 3 lines
drivers/char/lrng/Kconfig +3 -0
+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

#82 lore raw

Re: [PATCH v25 12/12] LRNG - add interface for gathering of raw entropy

In reply to Stephan Müller

Hi Stephan,

two general remarks on debugfs usage below

Quoted 5 lines · Stephan Müller
drivers/char/lrng/lrng_testing.c new file +0 -0
new file mode 100644
index 000000000000..5c33d3bd2172

<snip>

Quoted 29 lines
drivers/char/lrng/lrng_testing.c new file +29 -0
+/*
+ * 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;
+}

drivers/char/lrng/lrng_testing.c line 277

Quoted 10 lines
drivers/char/lrng/lrng_testing.c new file +10 -0
+
+/* 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)).

Quoted 4 lines
drivers/char/lrng/lrng_testing.c new file +4 -0
+	return 0;
+}
+
+static struct file_operations lrng_raw_name_fops = {

drivers/char/lrng/lrng_testing.c

Quoted 10 lines
drivers/char/lrng/lrng_testing.c new file +10 -0
+	.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.

drivers/char/lrng/lrng_testing.c line 295

Quoted 4 lines
drivers/char/lrng/lrng_testing.c new file +4 -0
+	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

Quoted 29 lines
drivers/char/lrng/lrng_testing.c new file +29 -0
+	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 <[email protected]>");
+MODULE_DESCRIPTION("Kernel module for gathering raw entropy");
Signature · 2 lines
SUSE Software Solutions Germany GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg), GF: Felix Imendörffer
#83 lore raw

Re: [PATCH v25 12/12] LRNG - add interface for gathering of raw entropy

Am Donnerstag, 21. November 2019, 13:18:10 CET schrieb Nicolai Stange:

Hi Nicolai,

Quoted 57 lines

Hi Stephan,

two general remarks on debugfs usage below

Quoted 5 lines · Stephan Müller
(quoted diff) +0 -0

b/drivers/char/lrng/lrng_testing.c new file mode 100644 index 000000000000..5c33d3bd2172

drivers/char/lrng/lrng_testing.c new file +0 -0

<snip>

Quoted 29 lines

+/*
+ * This data structure holds the dentry's of the debugfs files establishing + * the interface to user space.
+ */

drivers/char/lrng/lrng_testing.c new file +25 -0
+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;
+}

drivers/char/lrng/lrng_testing.c line 277

Quoted 10 lines
drivers/char/lrng/lrng_testing.c new file +10 -0
+
+/* 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

Quoted 5 lines

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.

Quoted 11 lines
Quoted 11 lines
drivers/char/lrng/lrng_testing.c new file +10 -0
+	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)
+{
Quoted 8 lines

drivers/char/lrng/lrng_testing.c

Quoted 4 lines
drivers/char/lrng/lrng_testing.c new file +4 -0
+	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.

Quoted 4 lines

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.

Quoted 7 lines

drivers/char/lrng/lrng_testing.c line 295

Quoted 5 lines
drivers/char/lrng/lrng_testing.c new file +4 -0
+	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.

Quoted 26 lines

Thanks,

Nicolai

Quoted 21 lines
drivers/char/lrng/lrng_testing.c new file +21 -0
+	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);
Quoted 8 lines

drivers/char/lrng/lrng_testing.c line 324

Quoted 8 lines
drivers/char/lrng/lrng_testing.c new file +8 -0
+}
+
+module_init(lrng_raw_init);
+module_exit(lrng_raw_exit);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Stephan Mueller <[email protected]>");
+MODULE_DESCRIPTION("Kernel module for gathering raw entropy");

Ciao
Stephan

#84 lore raw

v26 cover /dev/random - a new approach with full SP800-90B

In reply to Stephan Müller

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" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>

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
Signature · 1 line
2.23.0
#85 lore raw

PATCH v26 1/12 Linux Random Number Generator

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" <[email protected]>
CC: "Alexander E. Patrakov" <[email protected]>
CC: "Ahmed S. Darwish" <[email protected]>
CC: "Theodore Y. Ts'o" <[email protected]>
CC: Willy Tarreau <[email protected]>
CC: Matthew Garrett <[email protected]>
CC: Vito Caputo <[email protected]>
CC: Andreas Dilger <[email protected]>
CC: Jan Kara <[email protected]>
CC: Ray Strode <[email protected]>
CC: William Jon McCann <[email protected]>
CC: zhangjs <[email protected]>
CC: Andy Lutomirski <[email protected]>
CC: Florian Weimer <[email protected]>
CC: Lennart Poettering <[email protected]>
CC: Nicolai Stange <[email protected]>
Mathematical aspects Reviewed-by: "Peter, Matthias" <[email protected]>

---
 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
MAINTAINERS +7 -0
index e4f170d8bc29..851d3c2ea1af 100644
@@ -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 <[email protected]>
+S:	Maintained
+W:	https://www.chronox.de/lrng.html
+F:	drivers/char/lrng/*
+F:	include/linux/lrng.h
+
 LIS3LV02D ACCELEROMETER DRIVER
 M:	Eric Piel <[email protected]>
 S:	Maintained
drivers/char/Kconfig +2 -0
index df0fc997dc3e..cebb3a62c2ca 100644
@@ -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
drivers/char/Makefile +8 -1
index 7c5ea6f9df14..46ede09fd6d3 100644
@@ -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
drivers/char/lrng/Kconfig new file +55 -0

55 lines not on this page · raw message

drivers/char/lrng/Makefile new file +9 -0
new file mode 100644
index 000000000000..2761623715d2
@@ -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 \
drivers/char/lrng/lrng_archrandom.c new file +92 -0

92 lines not on this page · raw message

drivers/char/lrng/lrng_aux.c new file +148 -0

148 lines not on this page · raw message

drivers/char/lrng/lrng_chacha20.c new file +329 -0

329 lines not on this page · raw message

drivers/char/lrng/lrng_interfaces.c new file +666 -0

666 lines not on this page · raw message

drivers/char/lrng/lrng_internal.h new file +311 -0

311 lines not on this page · raw message

drivers/char/lrng/lrng_pool.c new file +671 -0

671 lines not on this page · raw message

drivers/char/lrng/lrng_sdrng.c new file +420 -0

420 lines not on this page · raw message

drivers/char/lrng/lrng_sw_noise.c new file +144 -0

144 lines not on this page · raw message

include/linux/lrng.h new file +71 -0

71 lines not on this page · raw message

Signature · 1 line
2.23.0
#86 lore raw

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

Thank you for the patch! Yet something to improve:

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

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/[email protected] Intel Corporation

#87 lore raw

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

Am Sonntag, 24. November 2019, 23:44:13 CET schrieb kbuild test robot:

Hi kbuild,

Quoted 31 lines

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

All error/warnings (new ones prefixed by >>):

In file included from include/linux/printk.h:6:0,

Quoted 12 lines
                    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:
Quoted 2 lines
Quoted 2 lines

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.

Quoted 19 lines
    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)
                               ^~~~~~~~~~~~~~~~~
Quoted 2 lines
Quoted 2 lines

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
Quoted 8 lines
Quoted 1 line

216 core_initcall(lrng_init_time_source);

   217

---
0-DAY kernel test infrastructure Open Source Technology
Center https://lists.01.org/hyperkitty/list/[email protected] Intel Corporation

Ciao
Stephan

#88 lore raw

PATCH v26 2/12 LRNG - allocate one SDRNG instance per NUMA node

In reply to Stephan Müller

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" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>
---
 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
drivers/char/lrng/Makefile +2 -0
index 2761623715d2..a00cddb45773 100644
@@ -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
drivers/char/lrng/lrng_internal.h +5 -0
index 675ba28bd2e6..fb7890939089 100644
@@ -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 **************************/
 
drivers/char/lrng/lrng_numa.c new file +101 -0

101 lines not on this page · raw message

Signature · 1 line
2.23.0
#89 lore raw

PATCH v26 3/12 LRNG - sysctls and /proc interface

In reply to Stephan Müller

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" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>
---
 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
drivers/char/lrng/Makefile +1 -0
index a00cddb45773..b6240b73e33d 100644
@@ -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
drivers/char/lrng/lrng_interfaces.c +0 -1
index 39fc3282843e..11a810c09720 100644
@@ -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? */
drivers/char/lrng/lrng_internal.h +4 -0
index fb7890939089..cca6e3580030 100644
@@ -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 *******************************/
 
drivers/char/lrng/lrng_proc.c new file +179 -0

179 lines not on this page · raw message

Signature · 1 line
2.23.0
#90 lore raw

PATCH v26 4/12 LRNG - add switchable DRNG support

In reply to Stephan Müller

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" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>
---
 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
drivers/char/lrng/Kconfig +7 -0
index 1ba10fd421f3..c6e8eafd836c 100644
@@ -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
drivers/char/lrng/Makefile +1 -0
index b6240b73e33d..6bac97638767 100644
@@ -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
drivers/char/lrng/lrng_switch.c new file +185 -0

185 lines not on this page · raw message

Signature · 1 line
2.23.0
#91 lore raw

PATCH v26 5/12 crypto: DRBG - externalize DRBG functions for LRNG

In reply to Stephan Müller

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

CC "Eric W. Biederman" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>
---
 crypto/drbg.c         | 16 ++++++++++------
 include/crypto/drbg.h |  7 +++++++
 2 files changed, 17 insertions(+), 6 deletions(-)
crypto/drbg.c +10 -6
index b6929eb5f565..5561dd0f09e1 100644
@@ -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)
 {
include/crypto/drbg.h +7 -0
index 8c9af21efce1..c63b20375235 100644
@@ -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 */
Signature · 1 line
2.23.0
#92 lore raw

PATCH v26 6/12 LRNG - add SP800-90A DRBG extension

In reply to Stephan Müller

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" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>
---
 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
drivers/char/lrng/Kconfig +11 -0
index c6e8eafd836c..dcdf4ef83da5 100644
@@ -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
drivers/char/lrng/Makefile +1 -0
index 6bac97638767..e3a704b3466c 100644
@@ -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
drivers/char/lrng/lrng_drbg.c new file +261 -0

261 lines not on this page · raw message

Signature · 1 line
2.23.0
#93 lore raw

PATCH v26 7/12 LRNG - add kernel crypto API PRNG extension

In reply to Stephan Müller

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" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>
---
 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
drivers/char/lrng/Kconfig +10 -0
index dcdf4ef83da5..03e6e2ec356b 100644
@@ -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
drivers/char/lrng/Makefile +1 -0
index e3a704b3466c..027b6ea51c20 100644
@@ -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
drivers/char/lrng/lrng_kcapi.c new file +328 -0

328 lines not on this page · raw message

Signature · 1 line
2.23.0
#94 lore raw

PATCH v26 8/12 crypto: provide access to a static Jitter RNG state

In reply to Stephan Müller

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" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>
---
 crypto/jitterentropy.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)
crypto/jitterentropy.c +23 -0
index 77fa2120fe0c..3a815495f778 100644
@@ -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;
+}
Signature · 1 line
2.23.0
#95 lore raw

PATCH v26 9/12 LRNG - add Jitter RNG fast noise source

In reply to Stephan Müller

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" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>
---
 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
drivers/char/lrng/Kconfig +11 -0
index 03e6e2ec356b..80fc723c67d2 100644
@@ -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
drivers/char/lrng/Makefile +1 -0
index 027b6ea51c20..a87d800c9aae 100644
@@ -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
drivers/char/lrng/lrng_jent.c new file +88 -0

88 lines not on this page · raw message

Signature · 1 line
2.23.0
#96 lore raw

PATCH v26 10/12 LRNG - add TRNG support

In reply to Stephan Müller

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" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>
---
 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
drivers/char/lrng/Kconfig +22 -0
index 80fc723c67d2..122d67ee110e 100644
@@ -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
drivers/char/lrng/Makefile +1 -0
index a87d800c9aae..1c72bc060bce 100644
@@ -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
drivers/char/lrng/lrng_trng.c new file +297 -0

297 lines not on this page · raw message

Signature · 1 line
2.23.0
#97 lore raw

PATCH v26 11/12 LRNG - add SP800-90B compliant health tests

In reply to 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 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" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>
---
 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
drivers/char/lrng/Kconfig +56 -0
index 122d67ee110e..e6ca3acc1e48 100644
@@ -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
drivers/char/lrng/Makefile +1 -0
index 1c72bc060bce..0713e9c0aa6e 100644
@@ -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
drivers/char/lrng/lrng_health.c new file +409 -0

409 lines not on this page · raw message

Signature · 1 line
2.23.0
#98 lore raw

PATCH v26 12/12 LRNG - add interface for gathering of raw entropy

In reply to Stephan Müller

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" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>
---
 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
drivers/char/lrng/Kconfig +16 -0
index e6ca3acc1e48..9335761cb2ba 100644
@@ -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
drivers/char/lrng/Makefile +1 -0
index 0713e9c0aa6e..c0b6cc4301fe 100644
@@ -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
drivers/char/lrng/lrng_testing.c new file +269 -0

269 lines not on this page · raw message

Signature · 1 line
2.23.0
#99 lore raw

v27 cover /dev/random - a new approach with full SP800-90B

In reply to Stephan Müller

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" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>

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
Signature · 1 line
2.24.1
#100 lore raw

PATCH v27 1/12 Linux Random Number Generator

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" <[email protected]>
CC: "Alexander E. Patrakov" <[email protected]>
CC: "Ahmed S. Darwish" <[email protected]>
CC: "Theodore Y. Ts'o" <[email protected]>
CC: Willy Tarreau <[email protected]>
CC: Matthew Garrett <[email protected]>
CC: Vito Caputo <[email protected]>
CC: Andreas Dilger <[email protected]>
CC: Jan Kara <[email protected]>
CC: Ray Strode <[email protected]>
CC: William Jon McCann <[email protected]>
CC: zhangjs <[email protected]>
CC: Andy Lutomirski <[email protected]>
CC: Florian Weimer <[email protected]>
CC: Lennart Poettering <[email protected]>
CC: Nicolai Stange <[email protected]>
Mathematical aspects Reviewed-by: "Peter, Matthias" <[email protected]>

---
 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
MAINTAINERS +7 -0
index 8982c6e013b3..f9beac15783c 100644
@@ -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 <[email protected]>
+S:	Maintained
+W:	https://www.chronox.de/lrng.html
+F:	drivers/char/lrng/*
+F:	include/linux/lrng.h
+
 LIS3LV02D ACCELEROMETER DRIVER
 M:	Eric Piel <[email protected]>
 S:	Maintained
drivers/char/Kconfig +2 -0
index 26956c006987..1e758735f633 100644
@@ -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
drivers/char/Makefile +8 -1
index 7c5ea6f9df14..46ede09fd6d3 100644
@@ -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
drivers/char/lrng/Kconfig new file +67 -0

67 lines not on this page · raw message

drivers/char/lrng/Makefile new file +9 -0
new file mode 100644
index 000000000000..1d2a0211973d
@@ -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 \
drivers/char/lrng/lrng_archrandom.c new file +92 -0

92 lines not on this page · raw message

drivers/char/lrng/lrng_aux.c new file +148 -0

148 lines not on this page · raw message

drivers/char/lrng/lrng_chacha20.c new file +317 -0

317 lines not on this page · raw message

drivers/char/lrng/lrng_chacha20.h new file +25 -0
new file mode 100644
index 000000000000..0387ad59cfbc
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
+/*
+ * LRNG ChaCha20 definitions
+ *
+ * Copyright (C) 2016 - 2020, Stephan Mueller <[email protected]>
+ */
+
+#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);
+}
drivers/char/lrng/lrng_drng.c new file +397 -0

397 lines not on this page · raw message

drivers/char/lrng/lrng_interfaces.c new file +623 -0

623 lines not on this page · raw message

drivers/char/lrng/lrng_internal.h new file +296 -0

296 lines not on this page · raw message

drivers/char/lrng/lrng_lfsr.h new file +152 -0

152 lines not on this page · raw message

drivers/char/lrng/lrng_pool.c new file +585 -0

585 lines not on this page · raw message

drivers/char/lrng/lrng_sw_noise.c new file +102 -0

102 lines not on this page · raw message

drivers/char/lrng/lrng_sw_noise.h new file +57 -0

57 lines not on this page · raw message

include/linux/lrng.h new file +71 -0

71 lines not on this page · raw message

Signature · 1 line
2.24.1
#101 lore raw

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

Thank you for the patch! Perhaps something to improve:

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

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/[email protected] Intel Corporation

#102 lore raw

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

Am Donnerstag, 16. Januar 2020, 07:09:51 CET schrieb kbuild test robot:

Hi kbuild,

Quoted 10 lines

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.

Quoted 62 lines

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

sparse warnings: (new ones prefixed by >>)

Quoted 11 lines
Quoted 11 lines

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?

Quoted 10 lines
Quoted 10 lines

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;
Quoted 6 lines
Quoted 1 line

455 return mask;

   456	}
   457
   458	static ssize_t lrng_drng_write_common(const char __user *buffer,

size_t count, 459 u32

entropy_bits)

Quoted 32 lines
   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
Quoted 8 lines
   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 "

Quoted 5 lines
   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 "

Quoted 1 line
   504					     "bytes read)\n", current->comm, 

nbytes);

Quoted 19 lines
   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))
Quoted 8 lines
   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;

Quoted 13 lines
   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;
Quoted 8 lines
   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,

Quoted 11 lines
   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

Quoted 1 line

564 * in the upstream's RNG implementation. Yet, user

space

Quoted 1 line

565 * can trigger a reseed as easy as writing into /dev/

random

Quoted 30 lines
   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,
Quoted 1 line

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
Quoted 4 lines

---
0-DAY kernel test infrastructure Open Source Technology
Center https://lists.01.org/hyperkitty/list/[email protected] Intel Corporation

Ciao
Stephan

#103 lore raw

PATCH v27 2/12 LRNG - allocate one DRNG instance per NUMA node

In reply to Stephan Müller

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" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>
---
 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
drivers/char/lrng/Makefile +2 -0
index 1d2a0211973d..0a32f22c2c1a 100644
@@ -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
drivers/char/lrng/lrng_internal.h +5 -0
index c9a7bccd14a0..c2b0a467548e 100644
@@ -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 **************************/
 
drivers/char/lrng/lrng_numa.c new file +101 -0

101 lines not on this page · raw message

Signature · 1 line
2.24.1
#104 lore raw

PATCH v27 3/12 LRNG - sysctls and /proc interface

In reply to Stephan Müller

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" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>
---
 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
drivers/char/lrng/Makefile +1 -0
index 0a32f22c2c1a..e69c176f0161 100644
@@ -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
drivers/char/lrng/lrng_interfaces.c +0 -1
index ff40ed37ddd6..8c4bf53d86ec 100644
@@ -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? */
drivers/char/lrng/lrng_internal.h +4 -0
index c2b0a467548e..349152d3c1b0 100644
@@ -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 *******************************/
 
drivers/char/lrng/lrng_proc.c new file +163 -0

163 lines not on this page · raw message

Signature · 1 line
2.24.1
#105 lore raw

PATCH v27 4/12 LRNG - add switchable DRNG support

In reply to Stephan Müller

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" <[email protected]>
CC "Alexander E. Patrakov" <[email protected]>
CC "Ahmed S. Darwish" <[email protected]>
CC "Theodore Y. Ts'o" <[email protected]>
CC Willy Tarreau <[email protected]>
CC Matthew Garrett <[email protected]>
CC Vito Caputo <[email protected]>
CC Andreas Dilger <[email protected]>
CC Jan Kara <[email protected]>
CC Ray Strode <[email protected]>
CC William Jon McCann <[email protected]>
CC zhangjs <[email protected]>
CC Andy Lutomirski <[email protected]>
CC Florian Weimer <[email protected]>
CC Lennart Poettering <[email protected]>
CC Nicolai Stange <[email protected]>
---
 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
drivers/char/lrng/Kconfig +7 -0
index 56f13efd3592..cb701bb0b8b6 100644
@@ -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
drivers/char/lrng/Makefile +1 -0
index e69c176f0161..31cfe87c999e 100644
@@ -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
drivers/char/lrng/lrng_switch.c new file +179 -0

179 lines not on this page · raw message

Signature · 1 line
2.24.1
#106 lore raw

Re: [PATCH v27 04/12] LRNG - add switchable DRNG support

Thank you for the patch! Perhaps something to improve:

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

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 <[email protected]>
:::::: CC: 0day robot <[email protected]>

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/hyperkitty/list/[email protected] Intel Corporation

#107 lore raw

Re: [PATCH v27 04/12] LRNG - add switchable DRNG support

Am Samstag, 11. Januar 2020, 08:09:50 CET schrieb kbuild test robot:

Hi,

Quoted 29 lines

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

sparse warnings: (new ones prefixed by >>)

Quoted 2 lines
Quoted 2 lines

drivers/char/lrng/lrng_internal.h:239:39: sparse: sparse: context imbalance in 'lrng_drng_switch' - unexpected unlock

Quoted 7 lines

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

Quoted 4 lines

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

Quoted 13 lines

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 <[email protected]>
:::::: CC: 0day robot <[email protected]>

Quoted 4 lines

---
0-DAY kernel test infrastructure Open Source Technology
Center https://lists.01.org/hyperkitty/list/[email protected] 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