summaryrefslogtreecommitdiff
path: root/sys/src/libsec/port/genrandom.c
blob: f4fdebbd93f8bc56132f981ee0f01a957312aed0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include "os.h"
#include <libsec.h>

static void
init(Chachastate *cs)
{
	ulong seed[11];
	int i;

	for(i=0; i<nelem(seed); i++)
		seed[i] = truerand();

	setupChachastate(cs, (uchar*)&seed[0], 32, (uchar*)&seed[8], 12, 20);
	memset(seed, 0, sizeof(seed));
}

static void
fill(Chachastate *cs, uchar *p, int n)
{
	Chachastate c;

	c = *cs;
	chacha_encrypt((uchar*)&cs->input[4], 32, &c);
	if(++cs->input[13] == 0)
		if(++cs->input[14] == 0)
			++cs->input[15];

	chacha_encrypt(p, n, &c);
	memset(&c, 0, sizeof(c));
}

void
genrandom(uchar *p, int n)
{
	static QLock lk;
	static Chachastate cs;

	qlock(&lk);
	if(cs.rounds == 0)
		init(&cs);
	cs.input[4] ^= getpid();	/* fork protection */
	fill(&cs, p, n);
	qunlock(&lk);
}