usr.sbin/makefs/hammer2: Sync with recent userspace ondisk.c changes
[dragonfly.git] / sys / libkern / arc4random.c
blob6018558c398d2599ff48247f7a32850117d047c6
1 /*-
2 * THE BEER-WARE LICENSE
4 * <dan@FreeBSD.ORG> wrote this file. As long as you retain this notice you
5 * can do whatever you want with this stuff. If we meet some day, and you
6 * think this stuff is worth it, you can buy me a beer in return.
8 * Dan Moschuk
10 * $FreeBSD: src/sys/libkern/arc4random.c,v 1.3.2.2 2001/09/17 07:06:50 silby Exp $
13 #include <sys/types.h>
14 #include <sys/systm.h>
15 #include <sys/random.h>
16 #include <sys/libkern.h>
17 #include <sys/time.h>
19 #include <vm/vm_extern.h>
21 #define ARC4_MAXRUNS 16384
22 #define ARC4_RESEED_SECONDS 300
23 #define ARC4_KEYBYTES 32 /* 256 bit key */
25 struct arc4_data {
26 uint8_t arc4_i;
27 uint8_t arc4_j;
28 int arc4_numruns;
29 time_t arc4_nextreseed;
30 uint8_t arc4_sbox[256];
33 static struct arc4_data *arc4_data_pcpu[MAXCPU];
35 static uint8_t arc4_randbyte(struct arc4_data *);
37 static __inline void
38 arc4_swap(uint8_t *a, uint8_t *b)
40 uint8_t c;
42 c = *a;
43 *a = *b;
44 *b = c;
48 * Stir our S-box.
50 static void
51 arc4_randomstir(struct arc4_data *d)
53 uint8_t key[256];
54 int r, n;
57 * XXX read_random() returns unsafe numbers if the entropy
58 * device is not loaded -- MarkM.
60 r = read_random(key, ARC4_KEYBYTES, 1);
61 /* If r == 0 || -1, just use what was on the stack. */
62 if (r > 0) {
63 for (n = r; n < sizeof(key); n++)
64 key[n] = key[n % r];
67 for (n = 0; n < 256; n++) {
68 d->arc4_j = (d->arc4_j + d->arc4_sbox[n] + key[n]) % 256;
69 arc4_swap(&d->arc4_sbox[n], &d->arc4_sbox[d->arc4_j]);
73 * Discard early keystream, as per recommendations in:
74 * "(Not So) Random Shuffles of RC4" by Ilya Mironov.
76 for (n = 0; n < 768 * 4; n++)
77 arc4_randbyte(d);
79 /* Reset for next reseed cycle. */
80 d->arc4_nextreseed = time_uptime + ARC4_RESEED_SECONDS;
81 d->arc4_numruns = 0;
85 * Generate a random byte.
87 static uint8_t
88 arc4_randbyte(struct arc4_data *d)
90 uint8_t arc4_t;
92 d->arc4_i = (d->arc4_i + 1) % 256;
93 d->arc4_j = (d->arc4_j + d->arc4_sbox[d->arc4_i]) % 256;
95 arc4_swap(&d->arc4_sbox[d->arc4_i], &d->arc4_sbox[d->arc4_j]);
97 arc4_t = (d->arc4_sbox[d->arc4_i] + d->arc4_sbox[d->arc4_j]) % 256;
98 return d->arc4_sbox[arc4_t];
101 uint32_t
102 karc4random(void)
104 struct arc4_data *d = arc4_data_pcpu[mycpuid];
105 uint32_t ret;
107 if (++(d->arc4_numruns) > ARC4_MAXRUNS ||
108 time_uptime > d->arc4_nextreseed)
109 arc4_randomstir(d);
111 ret = arc4_randbyte(d);
112 ret |= arc4_randbyte(d) << 8;
113 ret |= arc4_randbyte(d) << 16;
114 ret |= arc4_randbyte(d) << 24;
116 return ret;
119 uint64_t
120 karc4random64(void)
122 struct arc4_data *d = arc4_data_pcpu[mycpuid];
123 uint64_t ret;
125 if (++(d->arc4_numruns) > ARC4_MAXRUNS ||
126 time_uptime > d->arc4_nextreseed)
127 arc4_randomstir(d);
129 ret = arc4_randbyte(d);
130 ret |= arc4_randbyte(d) << 8;
131 ret |= arc4_randbyte(d) << 16;
132 ret |= arc4_randbyte(d) << 24;
133 ret |= (uint64_t)arc4_randbyte(d) << 32;
134 ret |= (uint64_t)arc4_randbyte(d) << 40;
135 ret |= (uint64_t)arc4_randbyte(d) << 48;
136 ret |= (uint64_t)arc4_randbyte(d) << 56;
138 return ret;
141 void
142 karc4random_buf(void *ptr, size_t len)
144 struct arc4_data *d = arc4_data_pcpu[mycpuid];
145 uint8_t *p = ptr;
147 #if 0
148 /* No one call this function in ISR/ithread. */
149 crit_enter();
150 #endif
152 if (++(d->arc4_numruns) > ARC4_MAXRUNS ||
153 time_uptime > d->arc4_nextreseed)
154 arc4_randomstir(d);
156 while (len--)
157 *p++ = arc4_randbyte(d);
159 #if 0
160 crit_exit();
161 #endif
165 * Initialize our S-box to its beginning defaults.
167 void
168 arc4_init_pcpu(int cpuid)
170 struct arc4_data *d;
171 int n;
173 KASSERT(arc4_data_pcpu[cpuid] == NULL,
174 ("arc4 was initialized on cpu%d", cpuid));
176 d = (void *)kmem_alloc3(kernel_map, sizeof(*d), VM_SUBSYS_GD,
177 KM_CPU(cpuid));
178 memset(d, 0, sizeof(*d));
180 for (n = 0; n < 256; n++)
181 d->arc4_sbox[n] = (uint8_t)n;
183 arc4_randomstir(d);
186 * Discard early keystream, as per recommendations in:
187 * "(Not So) Random Shuffles of RC4" by Ilya Mironov.
189 for (n = 0; n < 768 * 4; n++)
190 arc4_randbyte(d);
192 arc4_data_pcpu[cpuid] = d;