summaryrefslogtreecommitdiff
path: root/src/lib/libc/crypt/arc4random.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libc/crypt/arc4random.c')
-rw-r--r--src/lib/libc/crypt/arc4random.c176
1 files changed, 176 insertions, 0 deletions
diff --git a/src/lib/libc/crypt/arc4random.c b/src/lib/libc/crypt/arc4random.c
new file mode 100644
index 0000000000..5279c21518
--- /dev/null
+++ b/src/lib/libc/crypt/arc4random.c
@@ -0,0 +1,176 @@
1/* $OpenBSD: arc4random.c,v 1.3 1998/03/22 19:01:16 niklas Exp $ */
2
3/*
4 * Arc4 random number generator for OpenBSD.
5 * Copyright 1996 David Mazieres <dm@lcs.mit.edu>.
6 *
7 * Modification and redistribution in source and binary forms is
8 * permitted provided that due credit is given to the author and the
9 * OpenBSD project (for instance by leaving this copyright notice
10 * intact).
11 */
12
13/*
14 * This code is derived from section 17.1 of Applied Cryptography,
15 * second edition, which describes a stream cipher allegedly
16 * compatible with RSA Labs "RC4" cipher (the actual description of
17 * which is a trade secret). The same algorithm is used as a stream
18 * cipher called "arcfour" in Tatu Ylonen's ssh package.
19 *
20 * Here the stream cipher has been modified always to include the time
21 * when initializing the state. That makes it impossible to
22 * regenerate the same random sequence twice, so this can't be used
23 * for encryption, but will generate good random numbers.
24 *
25 * RC4 is a registered trademark of RSA Laboratories.
26 */
27
28#include <fcntl.h>
29#include <stdlib.h>
30#include <unistd.h>
31#include <sys/types.h>
32#include <sys/time.h>
33
34#ifdef __GNUC__
35#define inline __inline
36#else /* !__GNUC__ */
37#define inline
38#endif /* !__GNUC__ */
39
40struct arc4_stream {
41 u_int8_t i;
42 u_int8_t j;
43 u_int8_t s[256];
44};
45
46int rs_initialized;
47static struct arc4_stream rs;
48
49static inline void
50arc4_init(as)
51 struct arc4_stream *as;
52{
53 int n;
54
55 for (n = 0; n < 256; n++)
56 as->s[n] = n;
57 as->i = 0;
58 as->j = 0;
59}
60
61static inline void
62arc4_addrandom(as, dat, datlen)
63 struct arc4_stream *as;
64 u_char *dat;
65 int datlen;
66{
67 int n;
68 u_int8_t si;
69
70 as->i--;
71 for (n = 0; n < 256; n++) {
72 as->i = (as->i + 1);
73 si = as->s[as->i];
74 as->j = (as->j + si + dat[n % datlen]);
75 as->s[as->i] = as->s[as->j];
76 as->s[as->j] = si;
77 }
78}
79
80static void
81arc4_stir(as)
82 struct arc4_stream *as;
83{
84 int fd;
85 struct {
86 struct timeval tv;
87 u_int8_t rnd[128 - sizeof(struct timeval)];
88 } rdat;
89
90 gettimeofday(&rdat.tv, NULL);
91 fd = open("/dev/arandom", O_RDONLY);
92 if (fd >= 0) {
93 read(fd, rdat.rnd, sizeof(rdat.rnd));
94 close(fd);
95 }
96 /* fd < 0? Ah, what the heck. We'll just take whatever was on the
97 * stack... */
98
99 arc4_addrandom(as, (void *) &rdat, sizeof(rdat));
100}
101
102static inline u_int8_t
103arc4_getbyte(as)
104 struct arc4_stream *as;
105{
106 u_int8_t si, sj;
107
108 as->i = (as->i + 1);
109 si = as->s[as->i];
110 as->j = (as->j + si);
111 sj = as->s[as->j];
112 as->s[as->i] = sj;
113 as->s[as->j] = si;
114 return (as->s[(si + sj) & 0xff]);
115}
116
117static inline u_int32_t
118arc4_getword(as)
119 struct arc4_stream *as;
120{
121 u_int32_t val;
122 val = arc4_getbyte(as) << 24;
123 val |= arc4_getbyte(as) << 16;
124 val |= arc4_getbyte(as) << 8;
125 val |= arc4_getbyte(as);
126 return val;
127}
128
129void
130arc4random_stir()
131{
132 if (!rs_initialized) {
133 arc4_init(&rs);
134 rs_initialized = 1;
135 }
136 arc4_stir(&rs);
137}
138
139void
140arc4random_addrandom(dat, datlen)
141 u_char *dat;
142 int datlen;
143{
144 if (!rs_initialized)
145 arc4random_stir();
146 arc4_addrandom(&rs, dat, datlen);
147}
148
149u_int32_t
150arc4random()
151{
152 if (!rs_initialized)
153 arc4random_stir();
154 return arc4_getword(&rs);
155}
156
157#if 0
158/*-------- Test code for i386 --------*/
159#include <stdio.h>
160#include <machine/pctr.h>
161int
162main(int argc, char **argv)
163{
164 const int iter = 1000000;
165 int i;
166 pctrval v;
167
168 v = rdtsc();
169 for (i = 0; i < iter; i++)
170 arc4random();
171 v = rdtsc() - v;
172 v /= iter;
173
174 printf("%qd cycles\n", v);
175}
176#endif