Index | Thread | Search

From:
Sylvain <sylvain@sysau.com>
Subject:
Low Entropy at boot
To:
tech@openbsd.org
Date:
Wed, 21 Aug 2024 12:20:08 -0700

Download raw body.

Thread
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 <stdint.h>
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

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;
}