source: rtems-libbsd/freebsd/sys/libkern/arc4random.c @ 3d1e767

55-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since 3d1e767 was 3d1e767, checked in by Sebastian Huber <sebastian.huber@…>, on 04/27/16 at 08:25:22

Directly use <sys/types.h> provided by Newlib

  • Property mode set to 100644
File size: 3.1 KB
Line 
1#include <machine/rtems-bsd-kernel-space.h>
2
3/*-
4 * THE BEER-WARE LICENSE
5 *
6 * <dan@FreeBSD.ORG> wrote this file.  As long as you retain this notice you
7 * can do whatever you want with this stuff.  If we meet some day, and you
8 * think this stuff is worth it, you can buy me a beer in return.
9 *
10 * Dan Moschuk
11 */
12
13#include <sys/cdefs.h>
14__FBSDID("$FreeBSD$");
15
16#include <sys/types.h>
17#include <rtems/bsd/sys/param.h>
18#include <sys/kernel.h>
19#include <sys/random.h>
20#include <sys/libkern.h>
21#include <rtems/bsd/sys/lock.h>
22#include <sys/mutex.h>
23#include <sys/time.h>
24
25#define ARC4_RESEED_BYTES 65536
26#define ARC4_RESEED_SECONDS 300
27#define ARC4_KEYBYTES (256 / 8)
28
29int arc4rand_iniseed_state = ARC4_ENTR_NONE;
30
31static u_int8_t arc4_i, arc4_j;
32static int arc4_numruns = 0;
33static u_int8_t arc4_sbox[256];
34static time_t arc4_t_reseed;
35static struct mtx arc4_mtx;
36
37static u_int8_t arc4_randbyte(void);
38
39static __inline void
40arc4_swap(u_int8_t *a, u_int8_t *b)
41{
42        u_int8_t c;
43
44        c = *a;
45        *a = *b;
46        *b = c;
47}       
48
49/*
50 * Stir our S-box.
51 */
52static void
53arc4_randomstir (void)
54{
55        u_int8_t key[256];
56        int r, n;
57        struct timeval tv_now;
58
59        /*
60         * XXX read_random() returns unsafe numbers if the entropy
61         * device is not loaded -- MarkM.
62         */
63        r = read_random(key, ARC4_KEYBYTES);
64        getmicrouptime(&tv_now);
65        mtx_lock(&arc4_mtx);
66        /* If r == 0 || -1, just use what was on the stack. */
67        if (r > 0) {
68                for (n = r; n < sizeof(key); n++)
69                        key[n] = key[n % r];
70        }
71
72        for (n = 0; n < 256; n++) {
73                arc4_j = (arc4_j + arc4_sbox[n] + key[n]) % 256;
74                arc4_swap(&arc4_sbox[n], &arc4_sbox[arc4_j]);
75        }
76        arc4_i = arc4_j = 0;
77
78        /* Reset for next reseed cycle. */
79        arc4_t_reseed = tv_now.tv_sec + ARC4_RESEED_SECONDS;
80        arc4_numruns = 0;
81
82        /*
83         * Throw away the first N words of output, as suggested in the
84         * paper "Weaknesses in the Key Scheduling Algorithm of RC4"
85         * by Fluher, Mantin, and Shamir.  (N = 256 in our case.)
86         */
87        for (n = 0; n < 256*4; n++)
88                arc4_randbyte();
89        mtx_unlock(&arc4_mtx);
90}
91
92/*
93 * Initialize our S-box to its beginning defaults.
94 */
95static void
96arc4_init(void)
97{
98        int n;
99
100        mtx_init(&arc4_mtx, "arc4_mtx", NULL, MTX_DEF);
101        arc4_i = arc4_j = 0;
102        for (n = 0; n < 256; n++)
103                arc4_sbox[n] = (u_int8_t) n;
104
105        arc4_t_reseed = 0;
106}
107
108SYSINIT(arc4_init, SI_SUB_LOCK, SI_ORDER_ANY, arc4_init, NULL);
109
110/*
111 * Generate a random byte.
112 */
113static u_int8_t
114arc4_randbyte(void)
115{
116        u_int8_t arc4_t;
117
118        arc4_i = (arc4_i + 1) % 256;
119        arc4_j = (arc4_j + arc4_sbox[arc4_i]) % 256;
120
121        arc4_swap(&arc4_sbox[arc4_i], &arc4_sbox[arc4_j]);
122
123        arc4_t = (arc4_sbox[arc4_i] + arc4_sbox[arc4_j]) % 256;
124        return arc4_sbox[arc4_t];
125}
126
127/*
128 * MPSAFE
129 */
130void
131arc4rand(void *ptr, u_int len, int reseed)
132{
133        u_char *p;
134        struct timeval tv;
135
136        getmicrouptime(&tv);
137        if (atomic_cmpset_int(&arc4rand_iniseed_state, ARC4_ENTR_HAVE,
138            ARC4_ENTR_SEED) || reseed ||
139           (arc4_numruns > ARC4_RESEED_BYTES) ||
140           (tv.tv_sec > arc4_t_reseed))
141                arc4_randomstir();
142
143        mtx_lock(&arc4_mtx);
144        arc4_numruns += len;
145        p = ptr;
146        while (len--)
147                *p++ = arc4_randbyte();
148        mtx_unlock(&arc4_mtx);
149}
150
151uint32_t
152arc4random(void)
153{
154        uint32_t ret;
155
156        arc4rand(&ret, sizeof ret, 0);
157        return ret;
158}
Note: See TracBrowser for help on using the repository browser.