/dev/random - a new approach
Subsystems (2)
v38 cover /dev/random - a new approach
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. It provides the same API and ABI and can be used as a drop-in replacement.
The LRNG implements at least all features of the existing /dev/random such as NUMA-node-local DRNGs. Patches 1 through 3 provide the code that is feature- identical. The following advantages compared to the existing /dev/random implementation are present:
* Sole use of crypto for data processing:
- Exclusive use of a hash operation for conditioning entropy data with a clear mathematical description as given in [2] section 2.2 - non-cryptographic operations like LFSR are not used.
- The LRNG uses only properly defined and implemented cryptographic algorithms unlike the use of the SHA-1 transformation in the existing /dev/random implementation.
- Hash operations use NUMA-node-local hash instances to benefit large parallel systems.
- LRNG uses limited number of data post-processing steps as documented in
[2] section 2.2 compared to the large variation of different post-processing steps in the existing /dev/random implementation that have no apparent mathematical description (see [2] section 4.5).
* Performance
- Faster by up to 130% in the critical code path of the interrupt handler depending on data collection size configurable at kernel compile time - the default is now set such that the highest performance is achieved as outlined in [2] section 4.2.
- Configurable data collection sizes to accommodate small environments and big environments via CONFIG_LRNG_COLLECTION_SIZE.
- Entropy collection using an almost never contended lock to benefit large parallel systems – worst case rate of contention is the number of DRNG reseeds, usually the number of potential contentions per 10 minutes is equal to number of NUMA nodes.
- ChaCha20 DRNG is significantly faster as implemented in the existing /dev/random as demonstrated with [2] table 2.
- Faster entropy collection during boot time to reach fully seeded level, including on virtual systems or systems with SSDs as outlined in [2] section 4.1.
* Testing
- Availability of run-time health tests of the raw unconditioned noise source to identify degradation of the available entropy as documented in [2] section 2.5.4. Such health tests are important today due to virtual machine monitors reducing the resolution of or disabling the high-resolution timer.
- Heuristic entropy estimation is based on quantitative measurements and analysis following SP800-90B and not on coincidental underestimation of entropy applied by the existing /dev/random as outlined in [4] section 4.4.
- Power-on self tests for critical deterministic components (ChaCha20 DRNG, software hash implementation, and entropy collection logic) not already covered by power-up tests of the kernel crypto API as documented in [2] section 2.14.
- Availability of test interfaces for all operational stages of the LRNG including boot-time raw entropy event data sampling as outlined in [2] section 2.15.
- Fully testable ChaCha20 DRNG via a userspace ChaCha20 DRNG implementation [3].
- In case of using the kernel crypto API SHASH hash implementation, it is fully testable and tested via the NIST ACVP test framework, for example certificates A734, A737, and A738.
- The LRNG offers a test interface to validate the used software hash implementation and in particular that the LRNG invokes the hash correctly, allowing a NIST ACVP-compliant test cycle - see [2] section 2.15.
- Availability of stress testing covering the different code paths for data and mechanism (de)allocations and code paths covered with locks.
* Entropy collection
- The LRNG is shipped with test tools allowing the collection of raw unconditioned entropy during runtime and boot time available at [1].
- Full entropy assessment and description is provided with [2] chapter 3, specifically section 3.2.6.
- Guarantee that entropy events are not credited with entropy twice (the existing /dev/random implementation credits HID/disk and interrupt events with entropy which are a derivative of each other).
* Configurable
- LRNG kernel configuration allows configuration that is functionally equivalent to the existing /dev/random. Non-compiled additional code is folded into no-ops.
- The following additional functions are compile-time selectable independent of each other:
+ Enabling of switchable cryptographic implementation support. This allows enabling an SP800-90A DRBG.
+ Enabling of using Jitter RNG noise source.
+ Enabling of noise source health tests.
+ Enabling of test interface allowing to enable each test interface individually.
+ Enabling of the power-up self test.
- At boot-time, the SP800-90B health tests can be enabled as outlined in [2] section 2.5.4.
- At boot-time, the entropy rate used to credit the external CPU-based noise source and Jitter RNG noise source can be configured including setting an entropy rate of zero or full entropy - see [2] sections 2.5.2 and 2.5.3.
* Run-time pluggable cryptographic implementations used for all data processing steps specified in [2] section 2.2
- The DRNG can be replaced with a different implementation allowing any type of DRNG to provide data via the output interfaces. The LRNG provides the following types of DRNG implementations:
+ ChaCha20-based software implementation that is used per default.
+ SP800-90A DRBG using accelerated cryptographic implementations that may sleep.
+ Any DRNG that is accessible via the kernel crypto API RNG subsystem.
- The hash component can be replaced with any other hash implementation provided the implementation does not sleep. The LRNG provides the access to the following types of non-sleeping hash implementations:
+ SHA-256 software implementation that is used per default. Due to kernel build system inconsistencies, the software SHA-1 implementation is used if the kernel crypto API is not compiled.
+ SHA-512 hash using the fastest hash implementation available via the kernel crypto API SHASH subsystem.
* Code structure
- The LRNG source code is available for current upstream Linux kernel separate to the existing /dev/random which means that users who are conservative can use the unchanged existing /dev/random implementation.
- Back-port patches are available at [5] to apply the LRNG to Linux kernel versions of 5.8, 5.4, 4.19, 4.14, 4.12, and 4.10. Patches for other kernel versions are easily derived from the existing ones.
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".
An entropy analysis is performed on the following systems - details are given in [2] appendix C:
* x86 KVM virtualized guest 32 and 64 bit systems
* x86 bare metal
* older and newer ARMv7 system
* ARM64
* POWER7 LE and POWER 8 BE
* IBM Z System mainframe
* old MIPS embedded device
* testing with GCC and Clang
[1] https://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.
[2] https://www.chronox.de/lrng/doc/lrng.pdf
[3] https://www.chronox.de/chacha20_drng.html
[5] https://github.com/smuellerDD/lrng/tree/master/backports
Changes (compared to the previous patch set) - individual patches are visible at https://github.com/smuellerDD/lrng/commits/master:
- Use new SHA header files
- simplify code initializing ChaCha20
- simplify code processing time stamp
- Simplify code for self test
- use u32 instead of uint32_t
- increase entropy pool size config values
- report available pool size
- add hash update operation to add yet uncompressed entropy data in data array into entropy pool during DRNG seeding
- Support disabling of continuous compression - this allows a user to disable the continuous hash compression operation performed in interrupt context once the per-CPU data array is full. In this case, the continuous compression operation is disabled, the compression is performed when the DRNG is reseeded. This implies that no hash operation is performed in interrupt context at all and thus increases the performance even further. Yet, the drawback is that entropy data may be overwritten instead of compressed.
Stephan Mueller (13):
Linux Random Number Generator
LRNG - allocate one DRNG instance per NUMA node LRNG - sysctls and /proc interface
LRNG - add switchable DRNG support
LRNG - add common generic hash 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 | 31 +-
drivers/char/Kconfig | 2 +
drivers/char/Makefile | 9 +-
drivers/char/lrng/Kconfig | 403 ++++++++++
drivers/char/lrng/Makefile | 20 +
drivers/char/lrng/lrng_archrandom.c | 93 +++
drivers/char/lrng/lrng_aux.c | 136 ++++
drivers/char/lrng/lrng_chacha20.c | 347 +++++++++
drivers/char/lrng/lrng_chacha20.h | 29 +
drivers/char/lrng/lrng_drbg.c | 197 +++++
drivers/char/lrng/lrng_drng.c | 406 +++++++++++
drivers/char/lrng/lrng_health.c | 407 +++++++++++
drivers/char/lrng/lrng_interfaces.c | 649 +++++++++++++++++
drivers/char/lrng/lrng_internal.h | 429 +++++++++++
drivers/char/lrng/lrng_jent.c | 88 +++
drivers/char/lrng/lrng_kcapi.c | 225 ++++++
drivers/char/lrng/lrng_kcapi_hash.c | 97 +++
drivers/char/lrng/lrng_kcapi_hash.h | 19 +
drivers/char/lrng/lrng_numa.c | 120 +++
drivers/char/lrng/lrng_pool.c | 449 ++++++++++++
drivers/char/lrng/lrng_proc.c | 184 +++++
drivers/char/lrng/lrng_selftest.c | 351 +++++++++
drivers/char/lrng/lrng_sw_noise.c | 669 +++++++++++++++++
drivers/char/lrng/lrng_sw_noise.h | 71 ++
drivers/char/lrng/lrng_switch.c | 207 ++++++
drivers/char/lrng/lrng_testing.c | 689 ++++++++++++++++++
include/crypto/drbg.h | 7 +
.../crypto/internal}/jitterentropy.h | 3 +
include/linux/lrng.h | 79 ++
32 files changed, 6432 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_kcapi_hash.c
create mode 100644 drivers/char/lrng/lrng_kcapi_hash.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.hSignature · 1 line
2.29.2
PATCH v38 1/13 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 a per-CPU entropy pool using a hash operation that can be changed during runtime. Per default, SHA-256 is used.
(a) When an interrupt occurs, the high-resolution time stamp is mixed
into the per-CPU entropy pool. 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 per-CPU entropy pool. This data is not credited with entropy by the LRNG.
(c) Device drivers may provide data that is mixed into an auxiliary
pool using the same hash that is used to process the per-CPU entropy 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 auxiliary 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 auxiliary 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 seed data for the DRNG is to be generated, all per-CPU entropy pools and the auxiliary pool are hashed. The message digest forms the new auxiliary pool state. At the same time, this data is used for seeding the DRNG.
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 per-CPU entropy pool. During boot time, until the fully seeded stage is reached, each time stamp with its 32 least significant bits is are concatenated. When 16 such events are received, they are injected into the per-CPU entropy pool.
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. Truncation: The received time stamps are truncated to 8 least significant bits (or 32 least significant bits during boot time)
2. Concatenation: The received and truncated time stamps as well as auxiliary 32 bit words are concatenated to fill the per-CPU data array that is capable of holding 64 8-bit words.
3. Hashing: A set of concatenated time stamp data received from the interrupts are hashed together with the current existing per-CPU entropy pool state. The resulting message digest is the new per-CPU entropy pool state.
4. Hashing: When new data is added to the auxiliary pool, the data is hashed together with the auxiliary pool to form a new auxiliary pool state.
5. Hashing: A message digest of all per-CPU entropy pools and the auxiliary pool is calculated which forms the new auxiliary pool state. At the same time, this message digest is used to fill the slow noise source output buffer discussed in the following.
6. Truncation: The most-significant bits (MSB) defined by the requested number of bits (commonly equal to the security strength of the DRBG) or the entropy available transported with the buffer (which is the minimum of the message digest size and the available entropy in all entropy pools and the auxiliary pool), whatever is smaller, are obtained from the slow noise source output buffer.
7. Concatenation: The temporary seed buffer used to seed the DRNG is a concatenation of the slow noise source buffer, the Jitter RNG output, the CPU noise source output, and the current time.
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 and the getrandom system call are not processed.
The hash operation providing random data from the entropy pools will always require that all entropy sources collectively can deliver at least 128 entropy bits.
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.
To support smaller devices including IoT environments, this patch allows reducing the runtime memory footprint of the LRNG at compile time by selecting smaller collection data sizes.
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 in its fastest configuration executes within an average 55 cycles whereas the existing /dev/random on the same device takes about 97 cycles when measuring the execution time of add_interrupt_randomness().
* use of almost never contended lock for hashing operation to collect raw entropy supporting concurrency-free use of massive parallel systems - worst case rate of contention is the number of DRNG reseeds, usually: number of NUMA nodes contentions per 5 minutes.
* use of standalone ChaCha20 based RNG with the option to use a different DRNG selectable at compile time
* instantiate one DRNG per NUMA node
* support for runtime switchable output DRNGs
* use of runtime-switchable hash for conditioning implementation following widely accepted approach
* compile-time selectable collection 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: Torsten Duwe <[email protected]>
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 | 122 +++++ drivers/char/lrng/Makefile | 9 + drivers/char/lrng/lrng_archrandom.c | 93 ++++ drivers/char/lrng/lrng_aux.c | 136 ++++++ drivers/char/lrng/lrng_chacha20.c | 347 +++++++++++++++ drivers/char/lrng/lrng_chacha20.h | 29 ++ drivers/char/lrng/lrng_drng.c | 406 +++++++++++++++++ drivers/char/lrng/lrng_interfaces.c | 651 +++++++++++++++++++++++++++ drivers/char/lrng/lrng_internal.h | 420 +++++++++++++++++ drivers/char/lrng/lrng_pool.c | 449 +++++++++++++++++++ drivers/char/lrng/lrng_sw_noise.c | 669 ++++++++++++++++++++++++++++ drivers/char/lrng/lrng_sw_noise.h | 71 +++ include/linux/lrng.h | 79 ++++ 16 files changed, 3498 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_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
@@ -10260,6 +10260,13 @@ F: Documentation/litmus-tests/ F: Documentation/memory-barriers.txt F: tools/memory-model/ +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
@@ -471,6 +471,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
@@ -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 +122 -0
122 lines not on this page · raw message
drivers/char/lrng/Makefile new file +9 -0
@@ -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 +93 -0
93 lines not on this page · raw message
drivers/char/lrng/lrng_aux.c new file +136 -0
136 lines not on this page · raw message
drivers/char/lrng/lrng_chacha20.c new file +347 -0
347 lines not on this page · raw message
drivers/char/lrng/lrng_chacha20.h new file +29 -0
@@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */ +/* +* LRNG ChaCha20 definitions +* +* Copyright (C) 2016 - 2021, 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) +{ +/* String "expand 32-byte k" */ + chacha20->constants[0 ] =0x61707865 ; + chacha20->constants[1 ] =0x3320646e ; + chacha20->constants[2 ] =0x79622d32 ; + chacha20->constants[3 ] =0x6b206574 ; +}
drivers/char/lrng/lrng_drng.c new file +406 -0
406 lines not on this page · raw message
drivers/char/lrng/lrng_interfaces.c new file +651 -0
651 lines not on this page · raw message
drivers/char/lrng/lrng_internal.h new file +420 -0
420 lines not on this page · raw message
drivers/char/lrng/lrng_pool.c new file +449 -0
449 lines not on this page · raw message
drivers/char/lrng/lrng_sw_noise.c new file +669 -0
302 lines not on this page · raw message
drivers/char/lrng/lrng_sw_noise.h new file +71 -0
71 lines not on this page · raw message
include/linux/lrng.h new file +79 -0
79 lines not on this page · raw message
The rest of this diff is not shown. View the raw message.
Signature · 1 line
2.29.2
Part of the diff is not shown here. View the raw message.
PATCH v38 2/13 LRNG - allocate one DRNG instance per NUMA node
In reply to Stephan MüllerIn 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.
--- drivers/char/lrng/Makefile | 2 + drivers/char/lrng/lrng_internal.h | 5 ++ drivers/char/lrng/lrng_numa.c | 120 ++++++++++++++++++++++++++++++ 3 files changed, 127 insertions(+) create mode 100644 drivers/char/lrng/lrng_numa.c
drivers/char/lrng/Makefile +2 -0
@@ -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
@@ -214,8 +214,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 */ /************************** Entropy pool management ***************************/
drivers/char/lrng/lrng_numa.c new file +120 -0
120 lines not on this page · raw message
Signature · 1 line
2.29.2
PATCH v38 3/13 LRNG - sysctls and /proc interface
In reply to Stephan MüllerThe 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
--- drivers/char/lrng/Makefile | 1 + drivers/char/lrng/lrng_interfaces.c | 2 - drivers/char/lrng/lrng_internal.h | 4 + drivers/char/lrng/lrng_proc.c | 184 ++++++++++++++++++++++++++++ 4 files changed, 189 insertions(+), 2 deletions(-) create mode 100644 drivers/char/lrng/lrng_proc.c
drivers/char/lrng/Makefile +1 -0
@@ -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 -2
@@ -38,8 +38,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
@@ -108,7 +108,11 @@ void lrng_cc20_init_state_boot(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 +184 -0
184 lines not on this page · raw message
Signature · 1 line
2.29.2
PATCH v38 4/13 LRNG - add switchable DRNG support
In reply to Stephan MüllerThe 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.
The hash extension must not sleep and must not maintain a separate state.
--- drivers/char/lrng/Kconfig | 7 ++ drivers/char/lrng/Makefile | 1 + drivers/char/lrng/lrng_switch.c | 207 ++++++++++++++++++++++++++++++++ 3 files changed, 215 insertions(+) create mode 100644 drivers/char/lrng/lrng_switch.c
drivers/char/lrng/Kconfig +7 -0
@@ -119,4 +119,11 @@ config LRNG_COLLECTION_SIZE default 4096 if LRNG_COLLECTION_SIZE_4096 default 8192 if LRNG_COLLECTION_SIZE_8192 +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
@@ -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 +207 -0
207 lines not on this page · raw message
Signature · 1 line
2.29.2
PATCH v38 5/13 LRNG - add common generic hash support
In reply to Stephan MüllerThe LRNG switchable DRNG support also allows the replacement of the hash implementation used as conditioning component. The common generic hash support code provides the required callbacks using the synchronous hash implementations of the kernel crypto API.
All synchronous hash implementations supported by the kernel crypto API can be used as part of the LRNG with this generic support.
The generic support is intended to be configured by separate switchable DRNG backends.
--- drivers/char/lrng/Kconfig | 7 +++ drivers/char/lrng/Makefile | 1 + drivers/char/lrng/lrng_kcapi_hash.c | 97 +++++++++++++++++++++++++++++ drivers/char/lrng/lrng_kcapi_hash.h | 19 ++++++ 4 files changed, 124 insertions(+) create mode 100644 drivers/char/lrng/lrng_kcapi_hash.c create mode 100644 drivers/char/lrng/lrng_kcapi_hash.h
drivers/char/lrng/Kconfig +7 -0
@@ -126,4 +126,11 @@ 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_KCAPI_HASH + bool + +endif # LRNG_DRNG_SWITCH + endif # LRNG
drivers/char/lrng/Makefile +1 -0
@@ -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_KCAPI_HASH) += lrng_kcapi_hash.o
drivers/char/lrng/lrng_kcapi_hash.c new file +97 -0
97 lines not on this page · raw message
drivers/char/lrng/lrng_kcapi_hash.h new file +19 -0
@@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */ +/* +* Copyright (C) 2020 - 2021, Stephan Mueller <[email protected]> +*/ + +#ifndef _LRNG_KCAPI_HASH_H +#define _LRNG_KCAPI_HASH_H + +#include <linux/module.h> + +void *lrng_kcapi_hash_alloc (const char *name); +u32 lrng_kcapi_hash_digestsize (void *hash); +void lrng_kcapi_hash_dealloc (void *hash); +int lrng_kcapi_hash_init (struct shash_desc *shash,void *hash); +int lrng_kcapi_hash_update (struct shash_desc *shash,const u8 *inbuf, +u32 inbuflen); +int lrng_kcapi_hash_final (struct shash_desc *shash,u8 *digest); + +#endif /* _LRNG_KCAPI_HASH_H */
Signature · 1 line
2.29.2
PATCH v38 6/13 crypto: DRBG - externalize DRBG functions for LRNG
In reply to Stephan MüllerThis patch allows several DRBG functions to be called by the LRNG kernel code paths outside the drbg.c file.
--- crypto/drbg.c | 16 ++++++++++------ include/crypto/drbg.h | 7 +++++++ 2 files changed, 17 insertions(+), 6 deletions(-)
crypto/drbg.c +10 -6
@@ -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
@@ -1214,7 +1216,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 ;
@@ -1235,12 +1237,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 ;
@@ -1321,6 +1324,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
@@ -1890,8 +1894,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 ;
@@ -1918,6 +1921,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
@@ -278,4 +278,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.29.2
PATCH v38 7/13 LRNG - add SP800-90A DRBG extension
In reply to Stephan MüllerUsing 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.
--- drivers/char/lrng/Kconfig | 10 ++ drivers/char/lrng/Makefile | 1 + drivers/char/lrng/lrng_drbg.c | 197 ++++++++++++++++++++++++++++++++++ 3 files changed, 208 insertions(+) create mode 100644 drivers/char/lrng/lrng_drbg.c
drivers/char/lrng/Kconfig +10 -0
@@ -131,6 +131,16 @@ if LRNG_DRNG_SWITCH config LRNG_KCAPI_HASH bool +config LRNG_DRBG + tristate "SP800-90A support for the LRNG" + depends on CRYPTO + select CRYPTO_DRBG_MENU + select CRYPTO_SHA512 + select LRNG_KCAPI_HASH + 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_full is provided by a DRBG. endif # LRNG_DRNG_SWITCH endif # LRNG
drivers/char/lrng/Makefile +1 -0
@@ -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_KCAPI_HASH) += lrng_kcapi_hash.o +obj-$(CONFIG_LRNG_DRBG) += lrng_drbg.o
drivers/char/lrng/lrng_drbg.c new file +197 -0
197 lines not on this page · raw message
Signature · 1 line
2.29.2
PATCH v38 8/13 LRNG - add kernel crypto API PRNG extension
In reply to Stephan MüllerAdd 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.
--- drivers/char/lrng/Kconfig | 13 ++ drivers/char/lrng/Makefile | 1 + drivers/char/lrng/lrng_kcapi.c | 225 +++++++++++++++++++++++++++++++++ 3 files changed, 239 insertions(+) create mode 100644 drivers/char/lrng/lrng_kcapi.c
drivers/char/lrng/Kconfig +13 -0
@@ -141,6 +141,19 @@ 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_full is provided by a DRBG. + +config LRNG_KCAPI + tristate "Kernel Crypto API support for the LRNG" + depends on CRYPTO + depends on !LRNG_DRBG + select CRYPTO_RNG + select LRNG_KCAPI_HASH + 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
@@ -13,3 +13,4 @@ obj-$(CONFIG_SYSCTL) += lrng_proc.o obj-$(CONFIG_LRNG_DRNG_SWITCH) += lrng_switch.o obj-$(CONFIG_LRNG_KCAPI_HASH) += lrng_kcapi_hash.o obj-$(CONFIG_LRNG_DRBG) += lrng_drbg.o +obj-$(CONFIG_LRNG_KCAPI) += lrng_kcapi.o
drivers/char/lrng/lrng_kcapi.c new file +225 -0
225 lines not on this page · raw message
Signature · 1 line
2.29.2
PATCH v38 9/13 crypto: provide access to a static Jitter RNG state
In reply to Stephan MüllerTo 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.
---
crypto/jitterentropy-kcapi.c | 3 +-
crypto/jitterentropy.c | 31 ++++++++++++++++++-
.../crypto/internal}/jitterentropy.h | 3 ++
3 files changed, 34 insertions(+), 3 deletions(-)
rename {crypto => include/crypto/internal}/jitterentropy.h (84%)crypto/jitterentropy-kcapi.c +1 -2
@@ -43,8 +43,7 @@#include <linux/fips.h> #include <linux/time.h> #include <crypto/internal/rng.h> - -#include "jitterentropy.h" +#include <crypto/internal/jitterentropy.h> /*************************************************************************** * Helper function
crypto/jitterentropy.c +30 -1
@@ -117,7 +117,7 @@ struct rand_data {#define JENT_EHEALTH 9/* Health test failed during initialization */ #define JENT_ERCT 10/* RCT failed during initialization */ -#include "jitterentropy.h" +#include <crypto/internal/jitterentropy.h> /*************************************************************************** * Adaptive Proportion Test
@@ -854,3 +854,32 @@ 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 , + .rct_count =0 , + .apt_observations =0 , + .apt_count =0 , + .apt_base =0 , + .apt_base_set =0 , + .health_failure =0 + }; + +if (jent_entropy_init ()) +return NULL ; + +return &lrng_jent_state; +}
include/crypto/internal/jitterentropy.h renamed from crypto/jitterentropy.h +3 -0
@@ -15,3 +15,6 @@ extern int jent_read_entropy(struct rand_data *ec, unsigned char *data,extern struct rand_data *jent_entropy_collector_alloc (unsigned int osr,unsigned int flags);extern void jent_entropy_collector_free (struct rand_data *entropy_collector); + +/* Access to statically allocated Jitter RNG instance */ +extern struct rand_data *jent_lrng_entropy_collector (void );
Signature · 1 line
2.29.2
PATCH v38 10/13 LRNG - add Jitter RNG fast noise source
In reply to Stephan MüllerThe 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.
--- drivers/char/lrng/Kconfig | 12 +++++ drivers/char/lrng/Makefile | 1 + drivers/char/lrng/lrng_jent.c | 88 +++++++++++++++++++++++++++++++++++ 3 files changed, 101 insertions(+) create mode 100644 drivers/char/lrng/lrng_jent.c
drivers/char/lrng/Kconfig +12 -0
@@ -156,4 +156,16 @@ config LRNG_KCAPI provided by the selected kernel crypto API RNG. endif # LRNG_DRNG_SWITCH +config LRNG_JENT + bool "Enable Jitter RNG as LRNG Seed Source" + depends on CRYPTO + select CRYPTO_JITTERENTROPY + help + The Linux RNG may use the Jitter RNG as noise source. Enabling + this option enables the use of the Jitter RNG. Its default + entropy level is 16 bits of entropy per 256 data bits delivered + by the Jitter RNG. This entropy level can be changed at boot + time or at runtime with the lrng_base.jitterrng configuration + variable. + endif # LRNG
drivers/char/lrng/Makefile +1 -0
@@ -14,3 +14,4 @@ obj-$(CONFIG_LRNG_DRNG_SWITCH) += lrng_switch.o obj-$(CONFIG_LRNG_KCAPI_HASH) += lrng_kcapi_hash.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.29.2
PATCH v38 11/13 LRNG - add SP800-90B compliant health tests
In reply to Stephan MüllerImplement 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 hash for the per-CPU entropy pool. Only if all three values are non-zero, the received time delta is considered to be non-stuck.
- SP800-90B Repetition Count Test (RCT): The LRNG uses an enhanced version of the RCT specified in SP800-90B section 4.4.1. Instead of counting identical back-to-back values, the input to the RCT is the counting of the stuck values during the processing of received interrupt events. The RCT is applied with alpha=2^-30 compliant to the recommendation of FIPS 140-2 IG 9.8. During the counting operation, the LRNG always calculates the RCT cut-off value of C. If that value exceeds the allowed cut-off value, the LRNG will trigger the health test failure discussed below. An error is logged to the kernel log that such RCT failure occurred. This test is only applied and enforced in FIPS mode, i.e. when the kernel compiled with CONFIG_CONFIG_FIPS is started with fips=1.
- SP800-90B Adaptive Proportion Test (APT): The LRNG implements the APT as defined in SP800-90B section 4.4.2. The applied significance level again is alpha=2^-30 compliant to the recommendation of FIPS 140-2 IG 9.8.
The aforementioned health tests are applied to the first 1,024 time stamps obtained from interrupt events. In case one error is identified for either the RCT, or the APT, the collected entropy is invalidated and the SP800-90B startup health test is restarted.
As long as the SP800-90B startup health test is not completed, all LRNG random number output interfaces that may block will block and not generate any data. This implies that only those potentially blocking interfaces are defined to provide random numbers that are seeded with the interrupt noise source being SP800-90B compliant. All other output interfaces will not be affected by the SP800-90B startup test and thus are not considered SP800-90B compliant.
At runtime, the SP800-90B APT and RCT are applied to each time stamp generated for a received interrupt. When either the APT and RCT indicates a noise source failure, the LRNG is reset to a state it has immediately after boot:
- all entropy counters are set to zero
- the SP800-90B startup tests are re-performed which implies that getrandom(2) would block again until new entropy was collected
To summarize, the following rules apply:
• SP800-90B compliant output interfaces
- /dev/random
- getrandom(2) system call
- get_random_bytes kernel-internal interface when being triggered by the callback registered with add_random_ready_callback
• SP800-90B non-compliant output interfaces
- /dev/urandom
- get_random_bytes kernel-internal interface called directly
- randomize_page kernel-internal interface
- get_random_u32 and get_random_u64 kernel-internal interfaces
- get_random_u32_wait, get_random_u64_wait, get_random_int_wait, and get_random_long_wait kernel-internal interfaces
If either the RCT, or the APT health test fails irrespective whether during initialization or runtime, the following actions occur:
1. The entropy of the entire entropy pool is invalidated.
2. All DRNGs are reset which imply that they are treated as being not seeded and require a reseed during next invocation.
3. The SP800-90B startup health test are initiated with all implications of the startup tests. That implies that from that point on, new events must be observed and its entropy must be inserted into the entropy pool before random numbers are calculated from the entropy pool.
Further details on the SP800-90B compliance and the availability of all test tools required to perform all tests mandated by SP800-90B are provided at [1].
The entire health testing code is compile-time configurable.
The patch provides a CONFIG_BROKEN configuration of the APT / RCT cutoff values which have a high likelihood to trigger the health test failure. The BROKEN APT cutoff is set to the exact mean of the expected value if the time stamps are equally distributed (512 time stamps divided by 16 possible values due to using the 4 LSB of the time stamp). The BROKEN RCT cutoff value is set to 1 which is likely to be triggered during regular operation.
--- drivers/char/lrng/Kconfig | 56 +++++ drivers/char/lrng/Makefile | 1 + drivers/char/lrng/lrng_health.c | 407 ++++++++++++++++++++++++++++++++ 3 files changed, 464 insertions(+) create mode 100644 drivers/char/lrng/lrng_health.c
drivers/char/lrng/Kconfig +56 -0
@@ -168,4 +168,60 @@ config LRNG_JENT time or at runtime with the lrng_base.jitterrng configuration variable. +config LRNG_HEALTH_TESTS + bool "Enable noise source online health tests" + help + The online health tests validate the noise source at + runtime for fatal errors. These tests include SP800-90B + compliant tests which are invoked if the system is booted + with fips=1. In case of fatal errors during active + SP800-90B tests, the issue is logged and the noise + data is discarded. These tests are required for full + compliance with SP800-90B. + + If unsure, say Y. + +config LRNG_RCT_BROKEN + bool "SP800-90B RCT with dangerous low cutoff value" + depends on LRNG_HEALTH_TESTS + depends on BROKEN + default n + help + This option enables a dangerously low SP800-90B repetitive + count test (RCT) cutoff value which makes it very likely + that the RCT is triggered to raise a self test failure. + + This option is ONLY intended for developers wanting to + test the effectiveness of the SP800-90B RCT health test. + + If unsure, say N. + +config LRNG_APT_BROKEN + bool "SP800-90B APT with dangerous low cutoff value" + depends on LRNG_HEALTH_TESTS + depends on BROKEN + default n + help + This option enables a dangerously low SP800-90B adaptive + proportion test (APT) cutoff value which makes it very + likely that the APT is triggered to raise a self test + failure. + + This option is ONLY intended for developers wanting to + test the effectiveness of the SP800-90B APT health test. + + If unsure, say N. + +# Default taken from SP800-90B sec 4.4.1 - significance level 2^-30 +config LRNG_RCT_CUTOFF + int + default 31 if !LRNG_RCT_BROKEN + default 1 if LRNG_RCT_BROKEN + +# Default taken from SP800-90B sec 4.4.2 - significance level 2^-30 +config LRNG_APT_CUTOFF + int + default 325 if !LRNG_APT_BROKEN + default 32 if LRNG_APT_BROKEN + endif # LRNG
drivers/char/lrng/Makefile +1 -0
@@ -15,3 +15,4 @@ obj-$(CONFIG_LRNG_KCAPI_HASH) += lrng_kcapi_hash.o obj-$(CONFIG_LRNG_DRBG) += lrng_drbg.o obj-$(CONFIG_LRNG_KCAPI) += lrng_kcapi.o obj-$(CONFIG_LRNG_JENT) += lrng_jent.o +obj-$(CONFIG_LRNG_HEALTH_TESTS) += lrng_health.o
drivers/char/lrng/lrng_health.c new file +407 -0
407 lines not on this page · raw message
Signature · 1 line
2.29.2
PATCH v38 12/13 LRNG - add interface for gathering of raw entropy
In reply to Stephan MüllerThe 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.
In addition, the test interface allows gathering of the concatenated raw entropy data to verify that the concatenation works appropriately. This includes sampling of the following raw data:
* high-resolution time stamp
* Jiffies
* IRQ number
* IRQ flags
* return instruction pointer
* interrupt register state
* array logic batching the high-resolution time stamp
Also, a testing interface to support ACVT of the hash implementation is provided. The reason why only hash testing is supported (as opposed to also provide testing for the DRNG) is the fact that the LRNG software hash implementation contains glue code that may warrant testing in addition to the testing of the software ciphers via the kernel crypto API. Also, for testing the CTR-DRBG, the underlying AES implementation would need to be tested. However, such AES test interface cannot be provided by the LRNG as it has no means to access the AES operation.
Finally, the execution duration for processing a time stamp can be obtained with the LRNG raw entropy interface.
If a test interface is not compiled, its code is a noop which has no impact on the performance.
--- drivers/char/lrng/Kconfig | 150 +++++++ drivers/char/lrng/Makefile | 1 + drivers/char/lrng/lrng_testing.c | 689 +++++++++++++++++++++++++++++++ 3 files changed, 840 insertions(+) create mode 100644 drivers/char/lrng/lrng_testing.c
drivers/char/lrng/Kconfig +150 -0
@@ -224,4 +224,154 @@ config LRNG_APT_CUTOFF default 325 if !LRNG_APT_BROKEN default 32 if LRNG_APT_BROKEN +menuconfig LRNG_TESTING_MENU + bool "LRNG testing interfaces" + depends on DEBUG_FS + help + Enable one or more of the following test interfaces. + + If unsure, say N. + +if LRNG_TESTING_MENU + +config LRNG_RAW_HIRES_ENTROPY + bool "Enable entropy test interface to hires timer noise source" + default y + help + The test interface allows a privileged process to capture + the raw unconditioned high resolution time stamp 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_hires + debugfs file. Using the option lrng_testing.boot_raw_hires_test=1 + the raw noise of the first 1000 entropy events since boot + can be sampled. + +config LRNG_RAW_JIFFIES_ENTROPY + bool "Enable entropy test interface to Jiffies noise source" + help + The test interface allows a privileged process to capture + the raw unconditioned Jiffies that is collected by + the LRNG for statistical analysis. This data is used for + seeding the LRNG if a high-resolution time stamp is not + available. If a high-resolution time stamp is detected, + the Jiffies value is not collected by the LRNG and no + data is provided via the test interface. Extracted noise + data is not used to seed the random number generator. + + The raw noise data can be obtained using the lrng_raw_jiffies + debugfs file. Using the option lrng_testing.boot_raw_jiffies_test=1 + the raw noise of the first 1000 entropy events since boot + can be sampled. + +config LRNG_RAW_IRQ_ENTROPY + bool "Enable entropy test interface to IRQ number noise source" + help + The test interface allows a privileged process to capture + the raw unconditioned interrupt number that is collected by + the LRNG for statistical analysis. This data is used for + seeding the random32 PRNG external to the LRNG if a + high-resolution time stamp is available or it will be used to + seed the LRNG otherwise. Extracted noise data is not used to + seed the random number generator. + + The raw noise data can be obtained using the lrng_raw_irq + debugfs file. Using the option lrng_testing.boot_raw_irq_test=1 + the raw noise of the first 1000 entropy events since boot + can be sampled. + +config LRNG_RAW_IRQFLAGS_ENTROPY + bool "Enable entropy test interface to IRQ flags noise source" + help + The test interface allows a privileged process to capture + the raw unconditioned interrupt flags that is collected by + the LRNG for statistical analysis. This data is used for + seeding the random32 PRNG external to the LRNG if a + high-resolution time stamp is available or it will be used to + seed the LRNG otherwise. Extracted noise data is not used to + seed the random number generator. + + The raw noise data can be obtained using the lrng_raw_irqflags + debugfs file. Using the option lrng_testing.boot_raw_irqflags_test=1 + the raw noise of the first 1000 entropy events since boot + can be sampled. + +config LRNG_RAW_RETIP_ENTROPY + bool "Enable entropy test interface to RETIP value noise source" + help + The test interface allows a privileged process to capture + the raw unconditioned return instruction pointer value + that is collected by the LRNG for statistical analysis. + This data is used for seeding the random32 PRNG external + to the LRNG if a high-resolution time stamp is available or + it will be used to seed the LRNG otherwise. Extracted noise + data is not used to seed the random number generator. + + The raw noise data can be obtained using the lrng_raw_retip + debugfs file. Using the option lrng_testing.boot_raw_retip_test=1 + the raw noise of the first 1000 entropy events since boot + can be sampled. + +config LRNG_RAW_REGS_ENTROPY + bool "Enable entropy test interface to IRQ register value noise source" + help + The test interface allows a privileged process to capture + the raw unconditioned interrupt register value that is + collected by the LRNG for statistical analysis. Extracted noise + data is not used to seed the random number generator. + + The raw noise data can be obtained using the lrng_raw_regs + debugfs file. Using the option lrng_testing.boot_raw_regs_test=1 + the raw noise of the first 1000 entropy events since boot + can be sampled. + +config LRNG_RAW_ARRAY + bool "Enable test interface to LRNG raw entropy storage array" + help + The test interface allows a privileged process to capture + the raw noise data that is collected by the LRNG + in the per-CPU array for statistical analysis. The purpose + of this interface is to verify that the array handling code + truly only concatenates data and provides the same entropy + rate as the raw unconditioned noise source when assessing + the collected data byte-wise. + + The data can be obtained using the lrng_raw_array debugfs + file. Using the option lrng_testing.boot_raw_array=1 + the raw noise of the first 1000 entropy events since boot + can be sampled. + +config LRNG_IRQ_PERF + bool "Enable LRNG interrupt performance monitor" + help + With this option, the performance monitor of the LRNG + interrupt handling code is enabled. The file provides + the execution time of the interrupt handler in + cycles. + + The interrupt performance data can be obtained using + the lrng_irq_perf debugfs file. Using the option + lrng_testing.boot_irq_perf=1 the performance data of + the first 1000 entropy events since boot can be sampled. + +config LRNG_ACVT_HASH + bool "Enable LRNG ACVT Hash interface" + help + With this option, the LRNG built-in hash function used for + auxiliary pool management and prior to switching the + cryptographic backends is made available for ACVT. The + interface allows writing of the data to be hashed + into the interface. The read operation triggers the hash + operation to generate message digest. + + The ACVT interface is available with the lrng_acvt_hash + debugfs file. + +config LRNG_TESTING + bool + default y if (LRNG_RAW_HIRES_ENTROPY || LRNG_RAW_JIFFIES_ENTROPY ||LRNG_RAW_IRQ_ENTROPY || LRNG_RAW_IRQFLAGS_ENTROPY || LRNG_RAW_RETIP_ENTROPY || LRNG_RAW_REGS_ENTROPY || LRNG_RAW_ARRAY || LRNG_IRQ_PERF || LRNG_ACVT_HASH) + +endif #LRNG_TESTING_MENU + endif # LRNG
drivers/char/lrng/Makefile +1 -0
@@ -16,3 +16,4 @@ obj-$(CONFIG_LRNG_DRBG) += lrng_drbg.o obj-$(CONFIG_LRNG_KCAPI) += lrng_kcapi.o obj-$(CONFIG_LRNG_JENT) += lrng_jent.o obj-$(CONFIG_LRNG_HEALTH_TESTS) += lrng_health.o +obj-$(CONFIG_LRNG_TESTING) += lrng_testing.o
drivers/char/lrng/lrng_testing.c new file +689 -0
689 lines not on this page · raw message
Signature · 1 line
2.29.2
PATCH v38 13/13 LRNG - add power-on and runtime self-tests
In reply to Stephan MüllerParts of the LRNG are already covered by self-tests, including:
* Self-test of SP800-90A DRBG provided by the Linux kernel crypto API.
* Self-test of the PRNG provided by the Linux kernel crypto API.
* Raw noise source data testing including SP800-90B compliant tests when enabling CONFIG_LRNG_HEALTH_TESTS
This patch adds the self-tests for the remaining critical functions of the LRNG that are essential to maintain entropy and provide cryptographic strong random numbers. The following self-tests are implemented:
* Self-test of the time array maintenance. This test verifies whether the time stamp array management to store multiple values in one integer implements a concatenation of the data.
* Self-test of the software hash implementation ensures that this function operates compliant to the FIPS 180-4 specification. The self-test performs a hash operation of a zeroized per-CPU data array.
* Self-test of the ChaCha20 DRNG is based on the self-tests that are already present and implemented with the stand-alone user space ChaCha20 DRNG implementation available at [1]. The self-tests cover different use cases of the DRNG seeded with known seed data.
The status of the LRNG self-tests is provided with the selftest_status SysFS file. If the file contains a zero, the self-tests passed. The value 0xffffffff means that the self-tests were not executed. Any other value indicates a self-test failure.
The self-test may be compiled to panic the system if the self-test fails.
All self-tests operate on private state data structures. This implies that none of the self-tests have any impact on the regular LRNG operations. This allows the self-tests to be repeated at runtime by writing anything into the selftest_status SysFS file.
[1] https://www.chronox.de/chacha20.html
--- drivers/char/lrng/Kconfig | 26 +++ drivers/char/lrng/Makefile | 1 + drivers/char/lrng/lrng_selftest.c | 351 ++++++++++++++++++++++++++++++ 3 files changed, 378 insertions(+) create mode 100644 drivers/char/lrng/lrng_selftest.c
drivers/char/lrng/Kconfig +26 -0
@@ -374,4 +374,30 @@ config LRNG_TESTING endif #LRNG_TESTING_MENU +config LRNG_SELFTEST + bool "Enable power-on and on-demand self-tests" + help + The power-on self-tests are executed during boot time + covering the ChaCha20 DRNG, the hash operation used for + processing the entropy pools and the auxiliary pool, and + the time stamp management of the LRNG. + + The on-demand self-tests are triggered by writing any + value into the SysFS file selftest_status. At the same + time, when reading this file, the test status is + returned. A zero indicates that all tests were executed + successfully. + + If unsure, say Y. + +if LRNG_SELFTEST + +config LRNG_SELFTEST_PANIC + bool "Panic the kernel upon self-test failure" + help + If the option is enabled, the kernel is terminated if an + LRNG power-on self-test failure is detected. + +endif # LRNG_SELFTEST + endif # LRNG
drivers/char/lrng/Makefile +1 -0
@@ -17,3 +17,4 @@ obj-$(CONFIG_LRNG_KCAPI) += lrng_kcapi.o obj-$(CONFIG_LRNG_JENT) += lrng_jent.o obj-$(CONFIG_LRNG_HEALTH_TESTS) += lrng_health.o obj-$(CONFIG_LRNG_TESTING) += lrng_testing.o +obj-$(CONFIG_LRNG_SELFTEST) += lrng_selftest.o
drivers/char/lrng/lrng_selftest.c new file +351 -0
351 lines not on this page · raw message
Signature · 1 line
2.29.2