From fdeaa9103e9cb1d2d5fe2a15c1e921cb58caa427 Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Sun, 25 Jul 2021 19:00:50 +1000 Subject: [PATCH] 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 --- doc/reference/random/index.rst | 6 +- drivers/entropy/Kconfig.rv32m1 | 4 +- .../nxp_kinetis/kwx/Kconfig.defconfig.mkw40z4 | 2 +- .../nxp_kinetis/kwx/Kconfig.defconfig.mkw41z4 | 4 +- subsys/random/CMakeLists.txt | 6 +- subsys/random/Kconfig | 11 +- subsys/random/rand32_xoroshiro128.c | 122 ------------------ .../rand32/prj_hw_random_xoroshiro.conf | 4 - tests/crypto/rand32/testcase.yaml | 5 - 9 files changed, 15 insertions(+), 149 deletions(-) delete mode 100644 subsys/random/rand32_xoroshiro128.c delete mode 100644 tests/crypto/rand32/prj_hw_random_xoroshiro.conf diff --git a/doc/reference/random/index.rst b/doc/reference/random/index.rst index 8b9a40d9d57..4413f87d5e2 100644 --- a/doc/reference/random/index.rst +++ b/doc/reference/random/index.rst @@ -42,7 +42,7 @@ An override of the default value can be specified in the SOC or board .. code-block:: none choice RNG_GENERATOR_CHOICE - default XOROSHIRO_RANDOM_GENERATOR + default XOSHIRO_RANDOM_GENERATOR endchoice 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 entropy gathering driver to generate random numbers. -:kconfig:`CONFIG_XOROSHIRO_RANDOM_GENERATOR` - enables the Xoroshiro128+ pseudo-random number generator, that uses the +:kconfig:`CONFIG_XOSHIRO_RANDOM_GENERATOR` + enables the Xoshiro128++ pseudo-random number generator, that uses the entropy driver as a seed source. The CSPRNG_GENERATOR_CHOICE choice group provides selection of the diff --git a/drivers/entropy/Kconfig.rv32m1 b/drivers/entropy/Kconfig.rv32m1 index 276ef983657..786b81e897f 100644 --- a/drivers/entropy/Kconfig.rv32m1 +++ b/drivers/entropy/Kconfig.rv32m1 @@ -12,7 +12,7 @@ config ENTROPY_RV32M1_TRNG driver based on the RV32M1 TRNG driver. # 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 - default XOROSHIRO_RANDOM_GENERATOR if ENTROPY_RV32M1_TRNG + default XOSHIRO_RANDOM_GENERATOR if ENTROPY_RV32M1_TRNG endchoice diff --git a/soc/arm/nxp_kinetis/kwx/Kconfig.defconfig.mkw40z4 b/soc/arm/nxp_kinetis/kwx/Kconfig.defconfig.mkw40z4 index 10495526818..e3178c2d6ad 100644 --- a/soc/arm/nxp_kinetis/kwx/Kconfig.defconfig.mkw40z4 +++ b/soc/arm/nxp_kinetis/kwx/Kconfig.defconfig.mkw40z4 @@ -47,7 +47,7 @@ choice CSPRNG_GENERATOR_CHOICE endchoice choice RNG_GENERATOR_CHOICE - default XOROSHIRO_RANDOM_GENERATOR + default XOSHIRO_RANDOM_GENERATOR endchoice config TINYCRYPT diff --git a/soc/arm/nxp_kinetis/kwx/Kconfig.defconfig.mkw41z4 b/soc/arm/nxp_kinetis/kwx/Kconfig.defconfig.mkw41z4 index f385a2f5440..40b227db50b 100644 --- a/soc/arm/nxp_kinetis/kwx/Kconfig.defconfig.mkw41z4 +++ b/soc/arm/nxp_kinetis/kwx/Kconfig.defconfig.mkw41z4 @@ -83,10 +83,10 @@ config TINYCRYPT # # 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 - default XOROSHIRO_RANDOM_GENERATOR + default XOSHIRO_RANDOM_GENERATOR endchoice endif # SOC_MKW41Z4 diff --git a/subsys/random/CMakeLists.txt b/subsys/random/CMakeLists.txt index 72e32927999..f2943b09fea 100644 --- a/subsys/random/CMakeLists.txt +++ b/subsys/random/CMakeLists.txt @@ -2,7 +2,6 @@ if (CONFIG_ENTROPY_DEVICE_RANDOM_GENERATOR OR CONFIG_TIMER_RANDOM_GENERATOR OR - CONFIG_XOROSHIRO_RANDOM_GENERATOR OR CONFIG_XOSHIRO_RANDOM_GENERATOR) zephyr_library() zephyr_library_sources_ifdef(CONFIG_USERSPACE rand32_handlers.c) @@ -15,8 +14,11 @@ if (CONFIG_TEST_RANDOM_GENERATOR) Use it carefully.") 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_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_CTR_DRBG_CSPRNG_GENERATOR rand32_ctr_drbg.c) diff --git a/subsys/random/Kconfig b/subsys/random/Kconfig index be2fab673f4..6a7364e4b15 100644 --- a/subsys/random/Kconfig +++ b/subsys/random/Kconfig @@ -24,7 +24,7 @@ choice RNG_GENERATOR_CHOICE If the entropy support of the platform has sufficient performance to support random request then select that. Otherwise, select the - XOROSHIRO algorithm + XOSHIRO algorithm config TIMER_RANDOM_GENERATOR bool "System timer clock based number generator" @@ -44,14 +44,9 @@ config ENTROPY_DEVICE_RANDOM_GENERATOR number generator source. config XOROSHIRO_RANDOM_GENERATOR - bool "Use Xoroshiro128+ as PRNG" - depends on ENTROPY_HAS_DRIVER + bool "Use Xoroshiro128+ as PRNG (DEPRECATED)" help - Enables the Xoroshiro128+ pseudo-random number generator, that uses - 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. + This is deprecated, please use XOSHIRO_RANDOM_GENERATOR instead. config XOSHIRO_RANDOM_GENERATOR bool "Use Xoshiro128++ as PRNG" diff --git a/subsys/random/rand32_xoroshiro128.c b/subsys/random/rand32_xoroshiro128.c deleted file mode 100644 index bd793c9bd6c..00000000000 --- a/subsys/random/rand32_xoroshiro128.c +++ /dev/null @@ -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 . - */ - -/* 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 -#include -#include -#include -#include - -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); diff --git a/tests/crypto/rand32/prj_hw_random_xoroshiro.conf b/tests/crypto/rand32/prj_hw_random_xoroshiro.conf deleted file mode 100644 index 4d3d3262253..00000000000 --- a/tests/crypto/rand32/prj_hw_random_xoroshiro.conf +++ /dev/null @@ -1,4 +0,0 @@ -CONFIG_ZTEST=y -CONFIG_LOG=y -CONFIG_ENTROPY_GENERATOR=y -CONFIG_XOROSHIRO_RANDOM_GENERATOR=y diff --git a/tests/crypto/rand32/testcase.yaml b/tests/crypto/rand32/testcase.yaml index cc6aaf34a61..12bd7937321 100644 --- a/tests/crypto/rand32/testcase.yaml +++ b/tests/crypto/rand32/testcase.yaml @@ -6,11 +6,6 @@ tests: extra_args: CONF_FILE=prj_sw_random_systimer.conf tags: crypto random security 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: extra_args: CONF_FILE=prj_hw_random_xoshiro.conf filter: CONFIG_ENTROPY_HAS_DRIVER