aboutsummaryrefslogblamecommitdiff
path: root/src/kernel/core/prng.c
blob: 77dff7df7e88595e9d03e8db48145dfc42e02249 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
                 
                   










                                     

                                          
                         

                                    
                                                      


                        





                                  










                                                           

                                          


                                                           

                          


                                   
#include <prng.h>
#include <thread.h>

#define EPOOLSIZE 2048

static uint32_t x = 211;
static int n = 0;
static char entropy[EPOOLSIZE];
static int entropy_count = 0;
static const uint32_t a = 16807;
static const uint32_t m = 0x7FFFFFFF;

uint16_t prng_word() {
	int st = enter_critical(CL_NOINT);

	if (++n >= 100) {
		n = 0;
		if (entropy_count) {
			x += entropy[--entropy_count];
		}
	}
	x = (x * a) % m;

	uint16_t ret = x & 0xFFFF;

	exit_critical(st);

	return ret;
}

void prng_bytes(uint8_t* out, size_t nbytes) {
	uint16_t *d = (uint16_t*)out;
	for (size_t i = 0; i < nbytes / 2; i++) {
		d[i] = prng_word();
	}
	if (nbytes & 1) out[nbytes-1] = prng_word() & 0xFF;
}

void prng_add_entropy(const uint8_t* ptr, size_t nbytes) {
	int st = enter_critical(CL_NOINT);

	while (nbytes-- && entropy_count < EPOOLSIZE - 1) {
		entropy[entropy_count++] = *(ptr++);
	}

	exit_critical(st);
}

/* vim: set ts=4 sw=4 tw=0 noet :*/