]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/libkern/arc4random.c
Introduce OpenBSD-like Random PIDs. Controlled by a sysctl knob
[FreeBSD/FreeBSD.git] / sys / libkern / arc4random.c
1 /*-
2  * THE BEER-WARE LICENSE
3  *
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.
7  *
8  * Dan Moschuk
9  *
10  * $FreeBSD$
11  */
12
13 #include <sys/libkern.h>
14 #include <sys/time.h>
15
16 static u_int8_t arc4_i, arc4_j;
17 static int arc4_initialized = 0;
18 static u_int8_t arc4_sbox[256];
19
20 static __inline void
21 arc4_swap(u_int8_t *a, u_int8_t *b)
22 {
23         u_int8_t c;
24
25         c = *a;
26         *a = *b;
27         *b = c;
28 }       
29
30 /*
31  * Initialize our S-box to its beginning defaults.
32  */
33 static void
34 arc4_init(void)
35 {
36         struct timespec ts;
37         u_int8_t key[256];
38         int n;
39
40         for (n = 0; n < 256; n++)
41                 arc4_sbox[n] = (u_int8_t) n;
42
43         nanotime(&ts);
44         srandom(ts.tv_sec ^ ts.tv_nsec);
45         for (n = 0; n < 256; n++)
46                 key[n] = random() % 256;
47
48         arc4_i = arc4_j = 0;
49         for (n = 0; n < 256; n++)
50         {
51                 arc4_j = arc4_j + arc4_sbox[n] + key[n];
52                 arc4_swap(&arc4_sbox[n], &arc4_sbox[arc4_j]);
53         }
54         arc4_initialized = 1;
55 }
56
57 /*
58  * Generate a random byte.
59  */
60 static u_int8_t
61 arc4_randbyte(void)
62 {
63         u_int8_t arc4_t;
64
65         arc4_i = (arc4_i + 1) % 256;
66         arc4_j = (arc4_j + arc4_sbox[arc4_i]) % 256;
67
68         arc4_swap(&arc4_sbox[arc4_i], &arc4_sbox[arc4_j]);
69
70         arc4_t = (arc4_sbox[arc4_i] + arc4_sbox[arc4_j]) % 256;
71         return arc4_sbox[arc4_t];
72 }
73
74 u_int32_t
75 arc4random(void)
76 {
77         u_int32_t ret;
78
79         /* Initialize array if needed. */
80         if (!arc4_initialized)
81                 arc4_init();
82
83         ret = arc4_randbyte();
84         ret |= arc4_randbyte() << 8;
85         ret |= arc4_randbyte() << 16;
86         ret |= arc4_randbyte() << 24;
87
88         return ret;
89 }