1 #if defined(ED25519_TEST)
2 /*
3 	ISAAC+ "variant", the paper is not clear on operator precedence and other
4 	things. This is the "first in, first out" option!
5 
6 	Not threadsafe or securely initialized, only for deterministic testing
7 */
8 typedef struct isaacp_state_t {
9 	uint32_t state[256];
10 	unsigned char buffer[1024];
11 	uint32_t a, b, c;
12 	size_t left;
13 } isaacp_state;
14 
15 #define isaacp_step(offset, mix) \
16 	x = mm[i + offset]; \
17 	a = (a ^ (mix)) + (mm[(i + offset + 128) & 0xff]); \
18 	y = (a ^ b) + mm[(x >> 2) & 0xff]; \
19 	mm[i + offset] = y; \
20 	b = (x + a) ^ mm[(y >> 10) & 0xff]; \
21 	U32TO8_LE(out + (i + offset) * 4, b);
22 
23 static void
isaacp_mix(isaacp_state * st)24 isaacp_mix(isaacp_state *st) {
25 	uint32_t i, x, y;
26 	uint32_t a = st->a, b = st->b, c = st->c;
27 	uint32_t *mm = st->state;
28 	unsigned char *out = st->buffer;
29 
30 	c = c + 1;
31 	b = b + c;
32 
33 	for (i = 0; i < 256; i += 4) {
34 		isaacp_step(0, ROTL32(a,13))
35 		isaacp_step(1, ROTR32(a, 6))
36 		isaacp_step(2, ROTL32(a, 2))
37 		isaacp_step(3, ROTR32(a,16))
38 	}
39 
40 	st->a = a;
41 	st->b = b;
42 	st->c = c;
43 	st->left = 1024;
44 }
45 
46 static void
isaacp_random(isaacp_state * st,void * p,size_t len)47 isaacp_random(isaacp_state *st, void *p, size_t len) {
48 	size_t use;
49 	unsigned char *c = (unsigned char *)p;
50 	while (len) {
51 		use = (len > st->left) ? st->left : len;
52 		memcpy(c, st->buffer + (sizeof(st->buffer) - st->left), use);
53 
54 		st->left -= use;
55 		c += use;
56 		len -= use;
57 
58 		if (!st->left)
59 			isaacp_mix(st);
60 	}
61 }
62 
63 void
ED25519_FN(ed25519_randombytes_unsafe)64 ED25519_FN(ed25519_randombytes_unsafe) (void *p, size_t len) {
65 	static int initialized = 0;
66 	static isaacp_state rng;
67 
68 	if (!initialized) {
69 		memset(&rng, 0, sizeof(rng));
70 		isaacp_mix(&rng);
71 		isaacp_mix(&rng);
72 		initialized = 1;
73 	}
74 
75 	isaacp_random(&rng, p, len);
76 }
77 #elif defined(ED25519_CUSTOMRANDOM)
78 
79 #include "ed25519-randombytes-custom.h"
80 
81 #else
82 
83 #include <openssl/rand.h>
84 
85 void
ED25519_FN(ed25519_randombytes_unsafe)86 ED25519_FN(ed25519_randombytes_unsafe) (void *p, size_t len) {
87 
88   RAND_bytes(p, (int) len);
89 
90 }
91 #endif
92