From: Sylvain Subject: Low Entropy at boot To: tech@openbsd.org Date: Wed, 21 Aug 2024 12:20:08 -0700 Hello OpenBSD Tech. Not sure how a mailing list work... This is me thinking aloud... I was installing one of the BSD on an old laptop the other day and got a message about the entropy sources being insufficient to ensure proper crypto configuration. This got me thinking about the true RNG I created that uses multiple threads and concurrent memory access to maintain an unstable and unpredictable state. This could be used at boot to supplement or replace a weak hardware generator. I included my source code to program that uses this technique to extract entropy from user space. I call this "synthetic chaos”. I figured if any operating system is interested in exploring this, it has to be OpenBSD. I am writing this in case someone think it can help alleviate deficiencies or unknown own flaws in hardware generators. This is not an algorithm, it is really three programs running concurrently and using unmitigated memory access in a clever way that allow imperfections in hardware to be observed all the way into the software layer. I hope it can be useful. Sylvain Saucier, Artist and philosopher. sylvain@sysau.art /* Public Domain, please append your contributions, respectfully. Version 1.0 - Sylvain Saucier (sylvain@sysau.com) - Original author */ #include #include #include #include typedef struct { volatile uint64_t * s_output; volatile uint64_t * s_input; int pause; int stop; pthread_mutex_t mutex; pthread_t thread; } _C4_node; typedef struct { volatile uint64_t shared_io[3]; _C4_node t[3]; } _C4_state; //replace with large prime numbers between (2^63 > 2^64) for best results int C4_hash_algo(volatile uint64_t * in, volatile uint64_t * out) { uint64_t acc = 1; uint64_t primes[128] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647}; for (int bit = 0; bit < 64; bit++) { * in = ( * in << 13) | ( * in >> (64 - 13)); acc = (acc << bit) | (acc >> (64 - bit)); acc *= primes[(2 * bit) + (1 & * in)];* out += acc ^ * in; }* out ^= acc; return 0; } void C4_pause(_C4_state * state) { for (int thr = 0; thr < 3; thr++) { pthread_mutex_lock( & (state -> t[thr].mutex)); state -> t[thr].pause = 1; } } void C4_start(_C4_state * icm) { for (int thr = 0; thr < 3; thr++) { pthread_mutex_unlock( & (icm -> t[thr].mutex)); } } void * C4_main(void * raw) { _C4_node * self__C4_state = (_C4_node * ) raw; while (1) { C4_hash_algo(self__C4_state -> s_output, self__C4_state -> s_input); if (self__C4_state -> pause) { if (!self__C4_state -> stop) pthread_exit(NULL); self__C4_state -> pause = 0; pthread_mutex_lock( & self__C4_state -> mutex); pthread_mutex_unlock( & self__C4_state -> mutex); } } return NULL; } void init(_C4_state * s) { for (int thr = 0; thr < 3; thr++) { s -> shared_io[thr] = 0; s -> t[thr].s_output = & (s -> shared_io[thr]); s -> t[thr].s_input = & (s -> shared_io[(thr + 1) % 3]); s -> t[thr].stop = 1; s -> t[thr].pause = 1; pthread_mutex_init( & (s -> t[thr].mutex), NULL); pthread_mutex_lock( & (s -> t[thr].mutex)); pthread_create( & (s -> t[thr].thread), NULL, & C4_main, & (s -> t[thr])); } C4_start(s); usleep(100); C4_pause(s); } void fill(_C4_state * state, uint64_t * buffer, uint64_t length) { C4_start(state); uint64_t answer = 0; for (int found = 0; found < length; found++) { usleep(30); for (int thr = 0; thr < 3; thr++) answer ^= state -> shared_io[thr]; buffer[found] = answer; } C4_pause(state); } int main(int argc, const char * argv[]) { uint64_t out; _C4_state state; init( & state); while (1) { fill( & state, & out, 1); fwrite( & out, sizeof(uint64_t), 1, stdout); } return 0; }