Chameleon

Chameleon Svn Source Tree

Root/branches/cparm/i386/libsaio/arc4random.c

1
2#include "libsaio.h"
3
4/*
5 * License for L15_Swap, L15_InitState, L_SCHEDULE, L15_KSA, L15_Discard, L15, L15_Byte
6 *
7 * Copyright (c) 2004, 2005, 2006 Robin J Carey. All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions, and the following disclaimer,
14 * without modification, immediately at the beginning of the file.
15 * 2. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
22 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 *
30 * $DragonFly: src/sys/kern/kern_nrandom.c,v 1.7 2008/08/01 04:42:30 dillon Exp $
31 */
32
33/*
34 * IMPORTANT NOTE: LByteType must be exactly 8-bits in size or this software
35 * will not function correctly.
36 */
37typedef unsigned char LByteType;
38#define L15_STATE_SIZE 256
39static LByteType L15_x, L15_y;
40static LByteType L15_start_x;
41static LByteType L15_state[L15_STATE_SIZE];
42
43/*
44 * PRIVATE FUNCS:
45 */
46static void L15(const LByteType * const key, const size_t keyLen);
47static void L15_Swap(const LByteType pos1, const LByteType pos2);
48static void L15_InitState(void);
49static void L15_KSA(const LByteType * const key,
50 const size_t keyLen);
51static void L15_Discard(const LByteType numCalls);
52/*
53 * PUBLIC INTERFACE:
54 */
55static LByteType L15_Byte(void);
56
57static __inline void
58L15_Swap(const LByteType pos1, const LByteType pos2)
59{
60const LByteType save1 = L15_state[pos1];
61
62L15_state[pos1] = L15_state[pos2];
63L15_state[pos2] = save1;
64}
65
66static void
67L15_InitState (void)
68{
69size_t i;
70for (i = 0; i < L15_STATE_SIZE; ++i)
71L15_state[i] = i;
72}
73
74#define L_SCHEDULE(xx) \
75 \
76for (i = 0; i < L15_STATE_SIZE; ++i) { \
77 L15_Swap(i, (stateIndex += (L15_state[i] + (xx)))); \
78}
79
80static void
81L15_KSA (const LByteType * const key, const size_t keyLen)
82{
83 size_t i, keyIndex;
84 LByteType stateIndex = 0;
85
86 L_SCHEDULE(keyLen);
87 for (keyIndex = 0; keyIndex < keyLen; ++keyIndex) {
88 L_SCHEDULE(key[keyIndex]);
89 }
90}
91
92static void
93L15_Discard(const LByteType numCalls)
94{
95 LByteType i;
96 for (i = 0; i < numCalls; ++i) {
97 (void)L15_Byte();
98 }
99}
100
101/*
102 * PUBLIC INTERFACE:
103 */
104static void
105L15(const LByteType * const key, const size_t keyLen)
106{
107 L15_x = L15_start_x = 0;
108 L15_y = L15_STATE_SIZE - 1;
109 L15_InitState();
110 L15_KSA(key, keyLen);
111 L15_Discard(L15_Byte());
112}
113
114static LByteType
115L15_Byte(void)
116{
117LByteType z;
118
119L15_Swap(L15_state[L15_x], L15_y);
120z = (L15_state [L15_x++] + L15_state[L15_y--]);
121if (L15_x == L15_start_x) {
122--L15_y;
123}
124return (L15_state[z]);
125}
126
127
128
129/*-
130 * THE BEER-WARE LICENSE
131 *
132 * <dan@FreeBSD.ORG> wrote this file. As long as you retain this notice you
133 * can do whatever you want with this stuff. If we meet some day, and you
134 * think this stuff is worth it, you can buy me a beer in return.
135 *
136 * Dan Moschuk
137 *
138 * $FreeBSD: src/sys/libkern/arc4random.c,v 1.3.2.2 2001/09/17 07:06:50 silby Exp $
139 */
140
141
142#defineARC4_MAXRUNS 16384
143#defineARC4_RESEED_SECONDS 300 * 18
144#defineARC4_KEYBYTES 32 /* 256 bit key */
145
146static u_int8_t arc4_i, arc4_j;
147static int arc4_initialized = 0;
148static int arc4_numruns = 0;
149static u_int8_t arc4_sbox[256];
150static u_int32_t arc4_tv_nextreseed;
151
152static u_int8_t arc4_randbyte(void);
153
154static __inline void
155arc4_swap(u_int8_t *a, u_int8_t *b)
156{
157u_int8_t c;
158
159c = *a;
160*a = *b;
161*b = c;
162}
163
164/*
165 * Stir our S-box.
166 */
167static void
168arc4_randomstir (void)
169{
170u_int8_t key[256];
171int r, n;
172
173/*
174 * XXX read_random() returns unsafe numbers if the entropy
175 * device is not loaded -- MarkM.
176 */
177
178{
179for (r = 0; r < ARC4_KEYBYTES; ++r)
180((u_char *)key)[r] = L15_Byte();
181}
182
183/* If r == 0 || -1, just use what was on the stack. */
184if (r > 0)
185{
186for (n = r; n < sizeof(key); n++)
187key[n] = key[n % r];
188}
189
190for (n = 0; n < 256; n++)
191{
192arc4_j = (arc4_j + arc4_sbox[n] + key[n]) % 256;
193arc4_swap(&arc4_sbox[n], &arc4_sbox[arc4_j]);
194}
195arc4_i = arc4_j = 0;
196
197/* Reset for next reseed cycle. */
198arc4_tv_nextreseed = time18();
199arc4_tv_nextreseed += ARC4_RESEED_SECONDS;
200arc4_numruns = 0;
201}
202
203/*
204 * Initialize our S-box to its beginning defaults.
205 */
206static void
207arc4_init(void)
208{
209int n;
210
211u_int32_t now = time18();
212L15((const LByteType *)&now, sizeof(u_int32_t));
213
214arc4_i = arc4_j = 0;
215for (n = 0; n < 256; n++)
216arc4_sbox[n] = (u_int8_t) n;
217
218arc4_randomstir();
219arc4_initialized = 1;
220
221/*
222 * Throw away the first N words of output, as suggested in the
223 * paper "Weaknesses in the Key Scheduling Algorithm of RC4"
224 * by Fluher, Mantin, and Shamir. (N = 256 in our case.)
225 */
226for (n = 0; n < 256*4; n++)
227arc4_randbyte();
228}
229
230/*
231 * Generate a random byte.
232 */
233static u_int8_t
234arc4_randbyte(void)
235{
236u_int8_t arc4_t;
237
238arc4_i = (arc4_i + 1) % 256;
239arc4_j = (arc4_j + arc4_sbox[arc4_i]) % 256;
240
241arc4_swap(&arc4_sbox[arc4_i], &arc4_sbox[arc4_j]);
242
243arc4_t = (arc4_sbox[arc4_i] + arc4_sbox[arc4_j]) % 256;
244return arc4_sbox[arc4_t];
245}
246
247void
248arc4rand(void *ptr, u_int len, int reseed)
249{
250u_char *p;
251u_int32_t tv_now;
252
253/* Initialize array if needed. */
254if (!arc4_initialized)
255arc4_init();
256
257tv_now = time18();
258
259if (reseed ||
260(arc4_numruns > ARC4_MAXRUNS) ||
261(tv_now > arc4_tv_nextreseed))
262arc4_randomstir();
263
264arc4_numruns += len;
265p = ptr;
266while (len--)
267*p++ = arc4_randbyte();
268}
269
270uint32_t
271arc4random(void)
272{
273uint32_t ret;
274
275arc4rand(&ret, sizeof ret, 0);
276return ret;
277}
278

Archive Download this file

Revision: 1804