From 03349f9fff3017f185a2c01d12074acc00f94e2f Mon Sep 17 00:00:00 2001 From: Martin Stein Date: Thu, 19 May 2022 18:12:20 +0200 Subject: [PATCH] lx_emul/random: re-seed the local PRNG regularly With this commit, the Xoroshiro128+ PRNG in lx_emul/random.cc gets wrapped by a new class that automatically re-seeds the PRNG with jitterentropy every 1024 * 1024 + random(0..4095) bytes of generated output. Ref #4397 --- repos/dde_linux/src/include/lx_emul/random.h | 3 +- repos/dde_linux/src/lib/lx_emul/random.cc | 118 +++++++++++++++---- 2 files changed, 97 insertions(+), 24 deletions(-) diff --git a/repos/dde_linux/src/include/lx_emul/random.h b/repos/dde_linux/src/include/lx_emul/random.h index 143090cba4..f1dc75d289 100644 --- a/repos/dde_linux/src/include/lx_emul/random.h +++ b/repos/dde_linux/src/include/lx_emul/random.h @@ -11,8 +11,7 @@ * 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, + * reviewed/audited for its security-related properties, so far. Thus, * we strongly advise against the use of the lx_emul randomness functions for * security-critical purposes. */ diff --git a/repos/dde_linux/src/lib/lx_emul/random.cc b/repos/dde_linux/src/lib/lx_emul/random.cc index 6a4b114dad..f679079454 100644 --- a/repos/dde_linux/src/lib/lx_emul/random.cc +++ b/repos/dde_linux/src/lib/lx_emul/random.cc @@ -11,8 +11,7 @@ * 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, + * reviewed/audited for its security-related properties, so far. Thus, * we strongly advise against the use of the lx_emul randomness functions for * security-critical purposes. */ @@ -87,29 +86,105 @@ class Xoroshiro_128_plus } }; -static uint64_t jitterentropy_gen_random_u64() + +class Entropy_source : Interface { - static rand_data *jent { nullptr }; - if (jent == nullptr) { - jitterentropy_init(Lx_kit::env().heap); + public: - 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; -} + virtual uint64_t gen_random_u64() = 0; +}; -static Xoroshiro_128_plus &xoroshiro() +/* + * A wrapper for the Xoroshiro128+ PRNG that reseeds the PRNG every + * 1024 * 1024 + random(0..4095) bytes of generated output. + */ +class Xoroshiro_128_plus_reseeding { - static Xoroshiro_128_plus xoroshiro { jitterentropy_gen_random_u64() }; + private: + + enum { NR_OF_GEN_BYTES_BASE_LIMIT = 1024 * 1024 }; + + Entropy_source &_entropy_src; + uint64_t _seed { 0 }; + size_t _nr_of_gen_bytes { 0 }; + size_t _nr_of_gen_bytes_limit { 0 }; + Constructible _xoroshiro { }; + + void _reseed() + { + _seed = _entropy_src.gen_random_u64(); + _nr_of_gen_bytes = 0; + _nr_of_gen_bytes_limit = + NR_OF_GEN_BYTES_BASE_LIMIT + (_seed & 0xfff); + + _xoroshiro.construct(_seed); + } + + public: + + Xoroshiro_128_plus_reseeding(Entropy_source &entropy_src) + : + _entropy_src { entropy_src } + { + _reseed(); + } + + uint64_t get_u64() + { + _nr_of_gen_bytes += 8; + if (_nr_of_gen_bytes >= _nr_of_gen_bytes_limit) { + _reseed(); + _nr_of_gen_bytes += 8; + } + return _xoroshiro->get_u64(); + } +}; + + +class Jitterentropy : public Entropy_source +{ + private: + + rand_data *_rand_data { nullptr }; + + Jitterentropy(Jitterentropy const &) = delete; + + Jitterentropy & operator = (Jitterentropy const &) = delete; + + public: + + Jitterentropy(Allocator &alloc) + { + jitterentropy_init(alloc); + + if (jent_entropy_init() != 0) { + error("jitterentropy library could not be initialized!"); + } + _rand_data = jent_entropy_collector_alloc(0, 0); + if (_rand_data == nullptr) { + error("jitterentropy could not allocate entropy collector!"); + } + } + + + /******************** + ** Entropy_source ** + ********************/ + + uint64_t gen_random_u64() override + { + uint64_t result; + jent_read_entropy(_rand_data, (char*)&result, sizeof(result)); + return result; + } +}; + + +static Xoroshiro_128_plus_reseeding &xoroshiro() +{ + static Jitterentropy jitterentropy { Lx_kit::env().heap }; + static Xoroshiro_128_plus_reseeding xoroshiro { jitterentropy }; return xoroshiro; } @@ -119,7 +194,7 @@ void lx_emul_gen_random_bytes(void *dst, { /* validate arguments */ if (dst == nullptr || nr_of_bytes == 0) { - Genode::error("lx_emul_gen_random_bytes called with invalid args!"); + error("lx_emul_gen_random_bytes called with invalid args!"); return; } /* fill up the destination with random 64-bit values as far as possible */ @@ -138,7 +213,6 @@ void lx_emul_gen_random_bytes(void *dst, } uint64_t const rand_u64 { xoroshiro().get_u64() }; Genode::memcpy(dst_char, &rand_u64, nr_of_bytes); - }