random: deprecate XOROSHIRO_RANDOM_GENERATOR

Deprecate the xoroshiro128+ PRNG algorithm in favour of xoshiro128++.
xoshiro128++ is a drop-in replacement which is invisible from the user
perspective.

xoroshiro128+ is unsuitable because it is explicitly a floating-point
PRNG, not a general-purpose PRNG. This means that the lower 4 bits of
the output are actually linear, not random (from the designers,
https://prng.di.unimi.it/). This means 1/8th of the generated data is
not random.

Additionally, xoroshiro128+ is not a 32bit algorithm, it operates on
64bit numbers. For the vast majority of Zephyr devices, this makes the
PRNG slower than it needs to be. The replacement (xoshiro128++) is
32bit, with no loss in state space (still 128 bit).

Signed-off-by: Jordan Yates <jordan.yates@data61.csiro.au>
This commit is contained in:
Jordan Yates 2021-07-25 19:00:50 +10:00 committed by Carles Cufí
commit fdeaa9103e
9 changed files with 15 additions and 149 deletions

View file

@ -42,7 +42,7 @@ An override of the default value can be specified in the SOC or board
.. code-block:: none .. code-block:: none
choice RNG_GENERATOR_CHOICE choice RNG_GENERATOR_CHOICE
default XOROSHIRO_RANDOM_GENERATOR default XOSHIRO_RANDOM_GENERATOR
endchoice endchoice
The random number generators available include: The random number generators available include:
@ -55,8 +55,8 @@ The random number generators available include:
enables a random number generator that uses the enabled hardware enables a random number generator that uses the enabled hardware
entropy gathering driver to generate random numbers. entropy gathering driver to generate random numbers.
:kconfig:`CONFIG_XOROSHIRO_RANDOM_GENERATOR` :kconfig:`CONFIG_XOSHIRO_RANDOM_GENERATOR`
enables the Xoroshiro128+ pseudo-random number generator, that uses the enables the Xoshiro128++ pseudo-random number generator, that uses the
entropy driver as a seed source. entropy driver as a seed source.
The CSPRNG_GENERATOR_CHOICE choice group provides selection of the The CSPRNG_GENERATOR_CHOICE choice group provides selection of the

View file

@ -12,7 +12,7 @@ config ENTROPY_RV32M1_TRNG
driver based on the RV32M1 TRNG driver. driver based on the RV32M1 TRNG driver.
# Don't use use the RV32M1 TRNG as a random source since it can be quite slow. # Don't use use the RV32M1 TRNG as a random source since it can be quite slow.
# Instead, use the software implemented xoroshiro RNG. # Instead, use the software implemented xoshiro RNG.
choice RNG_GENERATOR_CHOICE choice RNG_GENERATOR_CHOICE
default XOROSHIRO_RANDOM_GENERATOR if ENTROPY_RV32M1_TRNG default XOSHIRO_RANDOM_GENERATOR if ENTROPY_RV32M1_TRNG
endchoice endchoice

View file

@ -47,7 +47,7 @@ choice CSPRNG_GENERATOR_CHOICE
endchoice endchoice
choice RNG_GENERATOR_CHOICE choice RNG_GENERATOR_CHOICE
default XOROSHIRO_RANDOM_GENERATOR default XOSHIRO_RANDOM_GENERATOR
endchoice endchoice
config TINYCRYPT config TINYCRYPT

View file

@ -83,10 +83,10 @@ config TINYCRYPT
# #
# KW41Z TRNG entropy source cannot be used as a Hardware RNG source so # KW41Z TRNG entropy source cannot be used as a Hardware RNG source so
# use XOROSHIRO for PRNG # use XOSHIRO for PRNG
# #
choice RNG_GENERATOR_CHOICE choice RNG_GENERATOR_CHOICE
default XOROSHIRO_RANDOM_GENERATOR default XOSHIRO_RANDOM_GENERATOR
endchoice endchoice
endif # SOC_MKW41Z4 endif # SOC_MKW41Z4

View file

@ -2,7 +2,6 @@
if (CONFIG_ENTROPY_DEVICE_RANDOM_GENERATOR OR if (CONFIG_ENTROPY_DEVICE_RANDOM_GENERATOR OR
CONFIG_TIMER_RANDOM_GENERATOR OR CONFIG_TIMER_RANDOM_GENERATOR OR
CONFIG_XOROSHIRO_RANDOM_GENERATOR OR
CONFIG_XOSHIRO_RANDOM_GENERATOR) CONFIG_XOSHIRO_RANDOM_GENERATOR)
zephyr_library() zephyr_library()
zephyr_library_sources_ifdef(CONFIG_USERSPACE rand32_handlers.c) zephyr_library_sources_ifdef(CONFIG_USERSPACE rand32_handlers.c)
@ -15,8 +14,11 @@ if (CONFIG_TEST_RANDOM_GENERATOR)
Use it carefully.") Use it carefully.")
endif() endif()
# XOROSHIRO builds the XOSHIRO implementation because a Kconfig choice cannot
# select another choice as a means of deprecating the symbol. Swapping out the
# implementation lets out-of-tree users still build until the symbol is removed.
zephyr_library_sources_ifdef(CONFIG_TIMER_RANDOM_GENERATOR rand32_timer.c) zephyr_library_sources_ifdef(CONFIG_TIMER_RANDOM_GENERATOR rand32_timer.c)
zephyr_library_sources_ifdef(CONFIG_XOROSHIRO_RANDOM_GENERATOR rand32_xoroshiro128.c) zephyr_library_sources_ifdef(CONFIG_XOROSHIRO_RANDOM_GENERATOR rand32_xoshiro128.c)
zephyr_library_sources_ifdef(CONFIG_XOSHIRO_RANDOM_GENERATOR rand32_xoshiro128.c) zephyr_library_sources_ifdef(CONFIG_XOSHIRO_RANDOM_GENERATOR rand32_xoshiro128.c)
zephyr_library_sources_ifdef(CONFIG_CTR_DRBG_CSPRNG_GENERATOR rand32_ctr_drbg.c) zephyr_library_sources_ifdef(CONFIG_CTR_DRBG_CSPRNG_GENERATOR rand32_ctr_drbg.c)

View file

@ -24,7 +24,7 @@ choice RNG_GENERATOR_CHOICE
If the entropy support of the platform has sufficient performance If the entropy support of the platform has sufficient performance
to support random request then select that. Otherwise, select the to support random request then select that. Otherwise, select the
XOROSHIRO algorithm XOSHIRO algorithm
config TIMER_RANDOM_GENERATOR config TIMER_RANDOM_GENERATOR
bool "System timer clock based number generator" bool "System timer clock based number generator"
@ -44,14 +44,9 @@ config ENTROPY_DEVICE_RANDOM_GENERATOR
number generator source. number generator source.
config XOROSHIRO_RANDOM_GENERATOR config XOROSHIRO_RANDOM_GENERATOR
bool "Use Xoroshiro128+ as PRNG" bool "Use Xoroshiro128+ as PRNG (DEPRECATED)"
depends on ENTROPY_HAS_DRIVER
help help
Enables the Xoroshiro128+ pseudo-random number generator, that uses This is deprecated, please use XOSHIRO_RANDOM_GENERATOR instead.
the entropy driver as a seed source. This is a fast non-cryptographically
secure random number generator.
It is so named because it uses 128 bits of state.
config XOSHIRO_RANDOM_GENERATOR config XOSHIRO_RANDOM_GENERATOR
bool "Use Xoshiro128++ as PRNG" bool "Use Xoshiro128++ as PRNG"

View file

@ -1,122 +0,0 @@
/*
* Copyright (c) 2017 Intel Corporation
*
* SPDX-License-Identifier: CC0-1.0
*
* Based on code written in 2016 by David Blackman and Sebastiano Vigna
* (vigna@acm.org)
*
* To the extent possible under law, the author has dedicated all copyright
* and related and neighboring rights to this software to the public domain
* worldwide. This software is distributed without any warranty.
*
* See <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
/* This is the successor to xorshift128+. It is the fastest full-period
* generator passing BigCrush without systematic failures, but due to the
* relatively short period it is acceptable only for applications with a
* mild amount of parallelism; otherwise, use a xorshift1024* generator.
*
* Beside passing BigCrush, this generator passes the PractRand test suite
* up to (and included) 16TB, with the exception of binary rank tests, as
* the lowest bit of this generator is an LSFR. The next bit is not an
* LFSR, but in the long run it will fail binary rank tests, too. The
* other bits have no LFSR artifacts.
*
* We suggest to use a sign test to extract a random Boolean value, and
* right shifts to extract subsets of bits.
*
* Note that the generator uses a simulated rotate operation, which most C
* compilers will turn into a single instruction. In Java, you can use
* Long.rotateLeft(). In languages that do not make low-level rotation
* instructions accessible xorshift128+ could be faster.
*
* The state must be seeded so that it is not everywhere zero. If you have
* a 64-bit seed, we suggest to seed a splitmix64 generator and use its
* output to fill s.
*/
#include <init.h>
#include <device.h>
#include <drivers/entropy.h>
#include <kernel.h>
#include <string.h>
static uint64_t state[2];
static inline uint64_t rotl(const uint64_t x, int k)
{
return (x << k) | (x >> (64 - k));
}
static int xoroshiro128_initialize(const struct device *dev)
{
dev = device_get_binding(DT_CHOSEN_ZEPHYR_ENTROPY_LABEL);
if (!dev) {
return -EINVAL;
}
int32_t rc = entropy_get_entropy_isr(dev, (uint8_t *)&state,
sizeof(state), ENTROPY_BUSYWAIT);
if (rc == -ENOTSUP) {
/* Driver does not provide an ISR-specific API, assume it can
* be called from ISR context
*/
rc = entropy_get_entropy(dev, (uint8_t *)&state, sizeof(state));
}
if (rc < 0) {
return -EINVAL;
}
return 0;
}
static uint32_t xoroshiro128_next(void)
{
const uint64_t s0 = state[0];
uint64_t s1 = state[1];
const uint64_t result = s0 + s1;
s1 ^= s0;
state[0] = rotl(s0, 55) ^ s1 ^ (s1 << 14);
state[1] = rotl(s1, 36);
return (uint32_t)result;
}
uint32_t z_impl_sys_rand32_get(void)
{
uint32_t ret;
ret = xoroshiro128_next();
return ret;
}
void z_impl_sys_rand_get(void *dst, size_t outlen)
{
uint32_t ret;
uint32_t blocksize = 4;
uint32_t len = 0;
uint32_t *udst = (uint32_t *)dst;
while (len < outlen) {
ret = xoroshiro128_next();
if ((outlen-len) < sizeof(ret)) {
blocksize = outlen - len;
(void)memcpy(udst, &ret, blocksize);
} else {
(*udst++) = ret;
}
len += blocksize;
}
}
/* In-tree entropy drivers will initialize in PRE_KERNEL_1; ensure that they're
* initialized properly before initializing ourselves.
*/
SYS_INIT(xoroshiro128_initialize, PRE_KERNEL_2,
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);

View file

@ -1,4 +0,0 @@
CONFIG_ZTEST=y
CONFIG_LOG=y
CONFIG_ENTROPY_GENERATOR=y
CONFIG_XOROSHIRO_RANDOM_GENERATOR=y

View file

@ -6,11 +6,6 @@ tests:
extra_args: CONF_FILE=prj_sw_random_systimer.conf extra_args: CONF_FILE=prj_sw_random_systimer.conf
tags: crypto random security tags: crypto random security
min_ram: 16 min_ram: 16
crypto.rand32.random_hw_xoroshiro:
extra_args: CONF_FILE=prj_hw_random_xoroshiro.conf
filter: CONFIG_ENTROPY_HAS_DRIVER
tags: crypto entropy random security
min_ram: 16
crypto.rand32.random_hw_xoshiro: crypto.rand32.random_hw_xoshiro:
extra_args: CONF_FILE=prj_hw_random_xoshiro.conf extra_args: CONF_FILE=prj_hw_random_xoshiro.conf
filter: CONFIG_ENTROPY_HAS_DRIVER filter: CONFIG_ENTROPY_HAS_DRIVER