ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/ermyth/src/arc4random.C
Revision: 1.2
Committed: Tue Aug 28 17:12:24 2007 UTC (16 years, 8 months ago) by pippijn
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +1 -1 lines
State: FILE REMOVED
Log Message:
removed old files

File Contents

# Content
1 /*
2 * Arc4 random number generator for OpenBSD.
3 * Copyright 1996 David Mazieres <dm@lcs.mit.edu>.
4 *
5 * Modification and redistribution in source and binary forms is
6 * permitted provided that due credit is given to the author and the
7 * OpenBSD project (for instance by leaving this copyright notice
8 * intact).
9 */
10
11 /*
12 * This code is derived from section 17.1 of Applied Cryptography,
13 * second edition, which describes a stream cipher allegedly
14 * compatible with RSA Labs "RC4" cipher (the actual description of
15 * which is a trade secret). The same algorithm is used as a stream
16 * cipher called "arcfour" in Tatu Ylonen's ssh package.
17 *
18 * Here the stream cipher has been modified always to include the time
19 * when initializing the state. That makes it impossible to
20 * regenerate the same random sequence twice, so this can't be used
21 * for encryption, but will generate good random numbers.
22 *
23 * RC4 is a registered trademark of RSA Laboratories.
24 */
25
26 /*
27 * $FreeBSD: /usr/local/www/cvsroot/FreeBSD/src/lib/libc/gen/arc4random.c,v 1.10.8.1 2006/11/18 21:35:13 ache Exp $
28 * Modified for Atheme by Jilles Tjoelker
29 * $Id: arc4random.C,v 1.1 2007-07-19 08:24:56 pippijn Exp $
30 */
31
32 #include "atheme.h"
33
34 #ifndef HAVE_ARC4RANDOM
35
36 struct arc4_stream
37 {
38 unsigned char i;
39 unsigned char j;
40 unsigned char s[256];
41 };
42
43 #define RANDOMDEV "/dev/urandom"
44
45 static struct arc4_stream rs;
46 static int rs_initialized;
47 static int rs_stired;
48 static int arc4_count;
49
50 static inline unsigned char arc4_getbyte (struct arc4_stream *);
51 static void arc4_stir (struct arc4_stream *);
52
53 static inline void
54 arc4_init (struct arc4_stream *as)
55 {
56 int n;
57
58 for (n = 0; n < 256; n++)
59 as->s[n] = n;
60 as->i = 0;
61 as->j = 0;
62 }
63
64 static inline void
65 arc4_addrandom (struct arc4_stream *as, unsigned char *dat, int datlen)
66 {
67 int n;
68 unsigned char si;
69
70 as->i--;
71 for (n = 0; n < 256; n++)
72 {
73 as->i = (as->i + 1);
74 si = as->s[as->i];
75 as->j = (as->j + si + dat[n % datlen]);
76 as->s[as->i] = as->s[as->j];
77 as->s[as->j] = si;
78 }
79 }
80
81 static void
82 arc4_stir (struct arc4_stream *as)
83 {
84 int fd, n;
85 struct
86 {
87 struct timeval tv;
88 pid_t pid;
89 unsigned char rnd[128 - sizeof (struct timeval) - sizeof (pid_t)];
90 }
91 rdat;
92
93 gettimeofday (&rdat.tv, NULL);
94 rdat.pid = getpid ();
95 fd = open (RANDOMDEV, O_RDONLY, 0);
96 if (fd >= 0)
97 {
98 (void) read (fd, rdat.rnd, sizeof (rdat.rnd));
99 close (fd);
100 }
101 /* fd < 0? Ah, what the heck. We'll just take whatever was on the
102 * stack... */
103
104 arc4_addrandom (as, (unsigned char *) &rdat, sizeof (rdat));
105
106 /*
107 * Throw away the first N bytes of output, as suggested in the
108 * paper "Weaknesses in the Key Scheduling Algorithm of RC4"
109 * by Fluher, Mantin, and Shamir. N=1024 is based on
110 * suggestions in the paper "(Not So) Random Shuffles of RC4"
111 * by Ilya Mironov.
112 */
113 for (n = 0; n < 1024; n++)
114 (void) arc4_getbyte (as);
115 arc4_count = 400000;
116 }
117
118 static inline unsigned char
119 arc4_getbyte (struct arc4_stream *as)
120 {
121 unsigned char si, sj;
122
123 as->i = (as->i + 1);
124 si = as->s[as->i];
125 as->j = (as->j + si);
126 sj = as->s[as->j];
127 as->s[as->i] = sj;
128 as->s[as->j] = si;
129
130 return (as->s[(si + sj) & 0xff]);
131 }
132
133 static inline unsigned int
134 arc4_getword (struct arc4_stream *as)
135 {
136 unsigned int val;
137
138 val = arc4_getbyte (as) << 24;
139 val |= arc4_getbyte (as) << 16;
140 val |= arc4_getbyte (as) << 8;
141 val |= arc4_getbyte (as);
142
143 return (val);
144 }
145
146 static void
147 arc4_check_init (void)
148 {
149 if (rs_initialized)
150 return;
151
152 arc4_init (&rs);
153 rs_initialized = 1;
154 }
155
156 static void
157 arc4_check_stir (void)
158 {
159 if (!rs_stired || --arc4_count == 0)
160 {
161 arc4_stir (&rs);
162 rs_stired = 1;
163 }
164 }
165
166 void
167 arc4random_stir ()
168 {
169 arc4_check_init ();
170 arc4_stir (&rs);
171 }
172
173 void
174 arc4random_addrandom (unsigned char *dat, int datlen)
175 {
176 arc4_check_init ();
177 arc4_check_stir ();
178 arc4_addrandom (&rs, dat, datlen);
179 }
180
181 unsigned int
182 arc4random (void)
183 {
184 unsigned int rnd;
185
186 arc4_check_init ();
187 arc4_check_stir ();
188 rnd = arc4_getword (&rs);
189
190 return (rnd);
191 }
192
193 /* vim:cinoptions=>s,e0,n0,f0,{0,}0,^0,=s,ps,t0,c3,+s,(2s,us,)20,*30,gs,hs
194 * vim:ts=8
195 * vim:sw=8
196 * vim:noexpandtab
197 */
198
199 #endif /* !HAVE_ARC4RANDOM */