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, 9 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

# User Rev Content
1 pippijn 1.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 pippijn 1.2 * $Id: arc4random.C,v 1.1 2007-07-19 08:24:56 pippijn Exp $
30 pippijn 1.1 */
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 */