From ab0bce77ec912ce60fac372920520d2dd04ae730 Mon Sep 17 00:00:00 2001 From: Martin Stein Date: Thu, 19 May 2022 16:54:36 +0200 Subject: [PATCH] lx_emul & wireguard & wifi: centralized random.cc Both the Wifi driver and the WireGuard port used local implementations for their source of randomness. Wifi used a Xoroshiro128+ PRNG for rapid generation of random values but initialized this PRNG always with the same static seed value. WireGuard, in contrast, requested each random byte directly from the jitterentropy lib, which is considered to be very time intensive. This commit removes the local variants of random.cc and introduces a new centralized lx_emul/random.cc . The new variant combines the former approaches, so, that jitterentropy is accessed only in order to generate a random seed for a Xoroshiro128+ PRNG. Front-end requests for random values are then fulfilled efficiently via the PRNG. :Warning: The output of the Xoroshiro128+ PRNG that is used in the new implementation of the lx_emul randomness functions has known statistical problems (see https://en.wikipedia.org/wiki/Xoroshiro128%2B#Statistical_Quality). Furthermore, the integration of Xoroshir128+ with the lx_emul code was not reviewed/audited for its security-related properties, so far, and has the known deficiency of seeding the PRNG only once during initialization. Thus, we strongly advise against the use of the lx_emul randomness functions for security-critical purposes. Ref #4397 --- repos/dde_linux/src/app/wireguard/lx_emul.c | 8 +- .../src/app/wireguard/lx_emul/random.h | 27 ---- repos/dde_linux/src/app/wireguard/random.cc | 36 ----- repos/dde_linux/src/app/wireguard/target.inc | 3 +- repos/dde_linux/src/include/lx_emul/random.h | 50 ++++++ repos/dde_linux/src/lib/lx_emul/random.cc | 148 ++++++++++++++++++ repos/pc/lib/mk/wifi.inc | 4 +- repos/pc/recipes/src/pc_wifi_drv/used_apis | 3 +- repos/pc/src/lib/wifi/lx_emul.c | 9 +- repos/pc/src/lib/wifi/lx_emul.h | 3 - repos/pc/src/lib/wifi/random.cc | 111 ------------- 11 files changed, 213 insertions(+), 189 deletions(-) delete mode 100644 repos/dde_linux/src/app/wireguard/lx_emul/random.h delete mode 100644 repos/dde_linux/src/app/wireguard/random.cc create mode 100644 repos/dde_linux/src/include/lx_emul/random.h create mode 100644 repos/dde_linux/src/lib/lx_emul/random.cc delete mode 100644 repos/pc/src/lib/wifi/random.cc diff --git a/repos/dde_linux/src/app/wireguard/lx_emul.c b/repos/dde_linux/src/app/wireguard/lx_emul.c index 730dc18635..bed8660613 100644 --- a/repos/dde_linux/src/app/wireguard/lx_emul.c +++ b/repos/dde_linux/src/app/wireguard/lx_emul.c @@ -19,7 +19,7 @@ void get_random_bytes(void * buf,int nbytes) { - lx_emul_random_bytes(buf, nbytes); + lx_emul_gen_random_bytes(buf, nbytes); } @@ -37,7 +37,7 @@ int wait_for_random_bytes(void) u32 get_random_u32(void) { u8 buf[4]; - lx_emul_random_bytes(buf, sizeof(buf)); + lx_emul_gen_random_bytes(buf, sizeof(buf)); return *((u32*)&buf); } @@ -47,7 +47,7 @@ u32 get_random_u32(void) u32 prandom_u32(void) { u8 buf[4]; - lx_emul_random_bytes(buf, sizeof(buf)); + lx_emul_gen_random_bytes(buf, sizeof(buf)); return *((u32*)&buf); } @@ -56,7 +56,7 @@ u32 prandom_u32(void) int __must_check get_random_bytes_arch(void * buf,int nbytes) { - lx_emul_random_bytes(buf, nbytes); + lx_emul_gen_random_bytes(buf, nbytes); return 0; } diff --git a/repos/dde_linux/src/app/wireguard/lx_emul/random.h b/repos/dde_linux/src/app/wireguard/lx_emul/random.h deleted file mode 100644 index 9ed5f1eef0..0000000000 --- a/repos/dde_linux/src/app/wireguard/lx_emul/random.h +++ /dev/null @@ -1,27 +0,0 @@ -/** - * \brief Randomness generation of lx_emul - * \author Stefan Kalkowski - * \date 2022-01-12 - */ - -/* - * Copyright (C) 2022 Genode Labs GmbH - * - * This file is distributed under the terms of the GNU General Public License - * version 2. - */ - -#ifndef _LX_EMUL__RANDOM_H_ -#define _LX_EMUL__RANDOM_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -void lx_emul_random_bytes(void * buf, int bytes); - -#ifdef __cplusplus -} -#endif - -#endif /* _LX_EMUL__RANDOM_H_ */ diff --git a/repos/dde_linux/src/app/wireguard/random.cc b/repos/dde_linux/src/app/wireguard/random.cc deleted file mode 100644 index f6e7dd8936..0000000000 --- a/repos/dde_linux/src/app/wireguard/random.cc +++ /dev/null @@ -1,36 +0,0 @@ -/* - * \brief Randomness backend for lx_emul - * \author Stefan Kalkowski - * \date 2022-01-12 - */ - -/* - * Copyright (C) 2022 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#include -#include -#include -#include - - -extern "C" void lx_emul_random_bytes(void * buf, int bytes) -{ - static rand_data * jent = nullptr; - - if (!jent) { - jitterentropy_init(Lx_kit::env().heap); - - if (jent_entropy_init() != 0) - Genode::error("jitterentropy library could not be initialized!"); - - jent = jent_entropy_collector_alloc(0, 0); - if (!jent) - Genode::error("jitterentropy could not allocate entropy collector!"); - } - - jent_read_entropy(jent, (char*)buf, bytes); -} diff --git a/repos/dde_linux/src/app/wireguard/target.inc b/repos/dde_linux/src/app/wireguard/target.inc index 7cf9ebe747..0080d06b74 100644 --- a/repos/dde_linux/src/app/wireguard/target.inc +++ b/repos/dde_linux/src/app/wireguard/target.inc @@ -13,9 +13,10 @@ SRC_CC += ipv4_config.cc SRC_CC += irq.cc SRC_CC += main.cc SRC_CC += nic_connection.cc -SRC_CC += random.cc +SRC_CC += lx_emul/random.cc SRC_CC += uplink_connection.cc vpath %.cc $(GEN_DIR) +vpath %.cc $(REP_DIR)/src/lib CC_CXX_WARN_STRICT_CONVERSION = diff --git a/repos/dde_linux/src/include/lx_emul/random.h b/repos/dde_linux/src/include/lx_emul/random.h new file mode 100644 index 0000000000..143090cba4 --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/random.h @@ -0,0 +1,50 @@ +/** + * \brief Source of randomness in lx_emul + * \author Josef Soentgen + * \author Stefan Kalkowski + * \author Martin Stein + * \date 2022-05-19 + * + * :Warning: + * + * The output of the Xoroshiro128+ PRNG that is used in the implementation of + * the lx_emul randomness functions has known statistical problems (see + * https://en.wikipedia.org/wiki/Xoroshiro128%2B#Statistical_Quality). + * Furthermore, the integration of Xoroshir128+ with the lx_emul code was not + * reviewed/audited for its security-related properties, so far, and has the + * known deficiency of seeding the PRNG only once during initialization. Thus, + * we strongly advise against the use of the lx_emul randomness functions for + * security-critical purposes. + */ + +/* + * Copyright (C) 2022 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#ifndef _LX_EMUL__RANDOM_H_ +#define _LX_EMUL__RANDOM_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Write a certain number of consecutive, random byte values beginning at + * a given address. + */ +void lx_emul_gen_random_bytes(void *dst, + unsigned long nr_of_bytes); + +/** + * Return a random unsigned integer value. + */ +unsigned int lx_emul_gen_random_uint(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _LX_EMUL__RANDOM_H_ */ diff --git a/repos/dde_linux/src/lib/lx_emul/random.cc b/repos/dde_linux/src/lib/lx_emul/random.cc new file mode 100644 index 0000000000..6a4b114dad --- /dev/null +++ b/repos/dde_linux/src/lib/lx_emul/random.cc @@ -0,0 +1,148 @@ +/* + * \brief Source of randomness in lx_emul + * \author Josef Soentgen + * \author Stefan Kalkowski + * \author Martin Stein + * \date 2022-05-19 + * + * :Warning: + * + * The output of the Xoroshiro128+ PRNG that is used in the implementation of + * the lx_emul randomness functions has known statistical problems (see + * https://en.wikipedia.org/wiki/Xoroshiro128%2B#Statistical_Quality). + * Furthermore, the integration of Xoroshir128+ with the lx_emul code was not + * reviewed/audited for its security-related properties, so far, and has the + * known deficiency of seeding the PRNG only once during initialization. Thus, + * we strongly advise against the use of the lx_emul randomness functions for + * security-critical purposes. + */ + +/* + * Copyright (C) 2022 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +/* base/include */ +#include +#include +#include + +/* dde_linux/src/include */ +#include +#include + +/* contrib/linux/src/linux/crypto */ +#include + +using namespace Genode; + +/* + * Xoroshiro128+ written in 2014-2016 by Sebastiano Vigna (vigna@acm.org) + * + * (see http://xoroshiro.di.unimi.it/xorshift128plus.c and + * http://xoroshiro.di.unimi.it/splitmix64.c) + */ +class Xoroshiro_128_plus +{ + private: + + uint64_t _seed; + uint64_t _s[2]; + + uint64_t _splitmix64() + { + uint64_t z = (_seed += __UINT64_C(0x9E3779B97F4A7C15)); + z = (z ^ (z >> 30)) * __UINT64_C(0xBF58476D1CE4E5B9); + z = (z ^ (z >> 27)) * __UINT64_C(0x94D049BB133111EB); + return z ^ (z >> 31); + } + + static uint64_t _rotl(uint64_t const x, int k) + { + return (x << k) | (x >> (64 - k)); + } + + public: + + Xoroshiro_128_plus(uint64_t seed) : _seed(seed) + { + _s[0] = _splitmix64(); + _s[1] = _splitmix64(); + } + + uint64_t get_u64() + { + uint64_t const s0 = _s[0]; + uint64_t s1 = _s[1]; + uint64_t const result = s0 + s1; + + s1 ^= s0; + + _s[0] = _rotl(s0, 55) ^ s1 ^ (s1 << 14); + _s[1] = _rotl(s1, 36); + + return result; + } +}; + +static uint64_t jitterentropy_gen_random_u64() +{ + static rand_data *jent { nullptr }; + if (jent == nullptr) { + jitterentropy_init(Lx_kit::env().heap); + + if (jent_entropy_init() != 0) { + Genode::error("jitterentropy library could not be initialized!"); + } + jent = jent_entropy_collector_alloc(0, 0); + if (jent == nullptr) { + Genode::error("jitterentropy could not allocate entropy collector!"); + } + } + uint64_t result; + jent_read_entropy(jent, (char*)&result, sizeof(result)); + return result; +} + + +static Xoroshiro_128_plus &xoroshiro() +{ + static Xoroshiro_128_plus xoroshiro { jitterentropy_gen_random_u64() }; + return xoroshiro; +} + + +void lx_emul_gen_random_bytes(void *dst, + unsigned long nr_of_bytes) +{ + /* validate arguments */ + if (dst == nullptr || nr_of_bytes == 0) { + Genode::error("lx_emul_gen_random_bytes called with invalid args!"); + return; + } + /* fill up the destination with random 64-bit values as far as possible */ + char *dst_char { reinterpret_cast(dst) }; + unsigned long const nr_of_rounds { nr_of_bytes >> 3 }; + for (unsigned long round_idx { 0 }; round_idx < nr_of_rounds; round_idx++) { + + uint64_t const rand_u64 { xoroshiro().get_u64() }; + Genode::memcpy(dst_char, &rand_u64, 8); + dst_char += 8; + } + /* fill up remaining bytes from one additional random 64-bit value */ + nr_of_bytes -= (nr_of_rounds << 3); + if (nr_of_bytes == 0) { + return; + } + uint64_t const rand_u64 { xoroshiro().get_u64() }; + Genode::memcpy(dst_char, &rand_u64, nr_of_bytes); + +} + + +unsigned int lx_emul_gen_random_uint() +{ + return (unsigned int)xoroshiro().get_u64(); +} diff --git a/repos/pc/lib/mk/wifi.inc b/repos/pc/lib/mk/wifi.inc index 0db265de1a..2115410fd8 100644 --- a/repos/pc/lib/mk/wifi.inc +++ b/repos/pc/lib/mk/wifi.inc @@ -6,13 +6,13 @@ SHARED_LIB := yes LD_OPT += --version-script=$(TARGET_LIB_DIR)/symbol.map -LIBS += base pc_linux_generated pc_lx_emul +LIBS += base jitterentropy pc_linux_generated pc_lx_emul INC_DIR := $(TARGET_LIB_DIR) SRC_CC += wlan.cc SRC_CC += misc.cc SRC_CC += firmware.cc SRC_CC += socket_call.cc -SRC_CC += random.cc +SRC_CC += lx_emul/random.cc SRC_CC += time.cc SRC_C += dummies.c diff --git a/repos/pc/recipes/src/pc_wifi_drv/used_apis b/repos/pc/recipes/src/pc_wifi_drv/used_apis index e00fd16fee..300a5d60a2 100644 --- a/repos/pc/recipes/src/pc_wifi_drv/used_apis +++ b/repos/pc/recipes/src/pc_wifi_drv/used_apis @@ -1,10 +1,11 @@ base genode_c_api +jitterentropy libc +nic_session openssl os pc_linux -nic_session platform_session report_session timer_session diff --git a/repos/pc/src/lib/wifi/lx_emul.c b/repos/pc/src/lib/wifi/lx_emul.c index 813b771e2f..f950e464e1 100644 --- a/repos/pc/src/lib/wifi/lx_emul.c +++ b/repos/pc/src/lib/wifi/lx_emul.c @@ -14,6 +14,7 @@ #include #include +#include #include #include @@ -442,7 +443,7 @@ void __put_page(struct page * page) u32 get_random_u32(void) { - return lx_emul_get_random_u32(); + return lx_emul_gen_random_uint(); } @@ -451,7 +452,7 @@ int __must_check get_random_bytes_arch(void *buf, int nbytes) if (nbytes < 0) return -1; - lx_emul_get_random_bytes(buf, (unsigned long)nbytes); + lx_emul_gen_random_bytes(buf, (unsigned long)nbytes); return 0; } @@ -467,13 +468,13 @@ void get_random_bytes(void *buf, int nbytes) void prandom_bytes(void *buf, size_t bytes) { - lx_emul_get_random_bytes(buf, bytes); + lx_emul_gen_random_bytes(buf, bytes); } u32 prandom_u32(void) { - return lx_emul_get_random_u32(); + return lx_emul_gen_random_uint(); } diff --git a/repos/pc/src/lib/wifi/lx_emul.h b/repos/pc/src/lib/wifi/lx_emul.h index 86c5220732..0915c039ac 100644 --- a/repos/pc/src/lib/wifi/lx_emul.h +++ b/repos/pc/src/lib/wifi/lx_emul.h @@ -28,9 +28,6 @@ void lx_backtrace(void); void lx_emul_time_udelay(unsigned long usec); -void lx_emul_get_random_bytes(void *buf, unsigned long nbytes); -unsigned int lx_emul_get_random_u32(void); - int lx_emul_rfkill_get_any(void); void lx_emul_rfkill_switch_all(int blocked); diff --git a/repos/pc/src/lib/wifi/random.cc b/repos/pc/src/lib/wifi/random.cc deleted file mode 100644 index cd8ee6bafe..0000000000 --- a/repos/pc/src/lib/wifi/random.cc +++ /dev/null @@ -1,111 +0,0 @@ -/* - * \brief Linux random emulation code - * \author Josef Soentgen - * \date 2016-10-19 - * - * For all intents and purposes this random back end should be treated - * as a gloryfied counter. - */ - -/* - * Copyright (C) 2016-2021 Genode Labs GmbH - * - * This file is distributed under the terms of the GNU General Public License - * version 2. - */ - -/* Genode includes */ -#include -#include -#include - - -using Genode::uint64_t; - -/* - * Xoroshiro128+ written in 2014-2016 by Sebastiano Vigna (vigna@acm.org) - * - * (see http://xoroshiro.di.unimi.it/xorshift128plus.c and - * http://xoroshiro.di.unimi.it/splitmix64.c) - */ - -struct Xoroshiro -{ - uint64_t seed; - - uint64_t splitmix64() - { - uint64_t z = (seed += __UINT64_C(0x9E3779B97F4A7C15)); - z = (z ^ (z >> 30)) * __UINT64_C(0xBF58476D1CE4E5B9); - z = (z ^ (z >> 27)) * __UINT64_C(0x94D049BB133111EB); - return z ^ (z >> 31); - } - - Xoroshiro(uint64_t seed) : seed(seed) - { - s[0] = splitmix64(); - s[1] = splitmix64(); - } - - uint64_t s[2]; - - static uint64_t rotl(uint64_t const x, int k) { - return (x << k) | (x >> (64 - k)); - } - - uint64_t get() - { - uint64_t const s0 = s[0]; - uint64_t s1 = s[1]; - uint64_t const result = s0 + s1; - - s1 ^= s0; - - s[0] = rotl(s0, 55) ^ s1 ^ (s1 << 14); - s[1] = rotl(s1, 36); - - return result; - } -}; - - -static Xoroshiro &xoroshiro() -{ - static Xoroshiro inst(0x636864324d766931); - return inst; -} - - -/******************** - ** linux/random.h ** - ********************/ - -extern "C" void lx_emul_get_random_bytes(void *buf, unsigned long nbytes) -{ - if (!buf || !nbytes) - return; - - char *p = reinterpret_cast(buf); - - unsigned long const rounds = nbytes / 8; - for (unsigned long i = 0; i < rounds; i++) { - uint64_t const v = xoroshiro().get(); - - Genode::memcpy(p, &v, 8); - p += 8; - } - - unsigned long const remain = nbytes - rounds * 8; - if (!remain) { - return; - } - - uint64_t const v = xoroshiro().get(); - Genode::memcpy(p, &v, remain); -} - - -extern "C" unsigned int lx_emul_get_random_u32(void) -{ - return (unsigned int)xoroshiro().get(); -}