summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordm <>1996-12-28 06:33:01 +0000
committerdm <>1996-12-28 06:33:01 +0000
commita6820ba482520797f3c1550fdfc95a3953b5252a (patch)
treef23283519b1966dad3f7a1eb409ca77208d50573
parent03d7d5f0c4f026dfd9de6d005038c306183effbe (diff)
downloadopenbsd-a6820ba482520797f3c1550fdfc95a3953b5252a.tar.gz
openbsd-a6820ba482520797f3c1550fdfc95a3953b5252a.tar.bz2
openbsd-a6820ba482520797f3c1550fdfc95a3953b5252a.zip
arc4random() number generator, for use with things like RPC xid's.
-rw-r--r--src/lib/libc/crypt/Makefile.inc4
-rw-r--r--src/lib/libc/crypt/arc4random.c175
2 files changed, 177 insertions, 2 deletions
diff --git a/src/lib/libc/crypt/Makefile.inc b/src/lib/libc/crypt/Makefile.inc
index 7b576e9e19..753396d4e4 100644
--- a/src/lib/libc/crypt/Makefile.inc
+++ b/src/lib/libc/crypt/Makefile.inc
@@ -1,8 +1,8 @@
1# $OpenBSD: Makefile.inc,v 1.4 1996/06/03 22:20:33 niklas Exp $ 1# $OpenBSD: Makefile.inc,v 1.5 1996/12/28 06:33:00 dm Exp $
2 2
3.PATH: ${.CURDIR}/arch/${MACHINE_ARCH}/crypt ${.CURDIR}/crypt 3.PATH: ${.CURDIR}/arch/${MACHINE_ARCH}/crypt ${.CURDIR}/crypt
4 4
5SRCS+= crypt.c morecrypt.c md5crypt.c 5SRCS+= crypt.c morecrypt.c md5crypt.c arc4random.c
6 6
7MAN+= crypt.3 7MAN+= crypt.3
8MLINKS+=crypt.3 encrypt.3 crypt.3 setkey.3 crypt.3 des_cipher.3 8MLINKS+=crypt.3 encrypt.3 crypt.3 setkey.3 crypt.3 des_cipher.3
diff --git a/src/lib/libc/crypt/arc4random.c b/src/lib/libc/crypt/arc4random.c
new file mode 100644
index 0000000000..078f4eeea6
--- /dev/null
+++ b/src/lib/libc/crypt/arc4random.c
@@ -0,0 +1,175 @@
1/* $Id: arc4random.c,v 1.1 1996/12/28 06:33:01 dm 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 <stdlib.h>
29#include <fcntl.h>
30#include <sys/types.h>
31#include <sys/time.h>
32
33#ifdef __GNUC__
34#define inline __inline
35#else /* !__GNUC__ */
36#define inline
37#endif /* !__GNUC__ */
38
39struct arc4_stream {
40 u_int8_t i;
41 u_int8_t j;
42 u_int8_t s[256];
43};
44
45int rs_initialized;
46static struct arc4_stream rs;
47
48static inline void
49arc4_init(as)
50 struct arc4_stream *as;
51{
52 int n;
53
54 for (n = 0; n < 256; n++)
55 as->s[n] = n;
56 as->i = 0;
57 as->j = 0;
58}
59
60static inline void
61arc4_addrandom(as, dat, datlen)
62 struct arc4_stream *as;
63 u_char *dat;
64 int datlen;
65{
66 int n;
67 u_int8_t si;
68
69 as->i--;
70 for (n = 0; n < 256; n++) {
71 as->i = (as->i + 1);
72 si = as->s[as->i];
73 as->j = (as->j + si + dat[n % datlen]);
74 as->s[as->i] = as->s[as->j];
75 as->s[as->j] = si;
76 }
77}
78
79static void
80arc4_stir(as)
81 struct arc4_stream *as;
82{
83 int fd;
84 struct {
85 struct timeval tv;
86 u_int8_t rnd[128 - sizeof(struct timeval)];
87 } rdat;
88
89 gettimeofday(&rdat.tv, NULL);
90 fd = open("/dev/arandom", O_RDONLY);
91 if (fd >= 0) {
92 read(fd, rdat.rnd, sizeof(rdat.rnd));
93 close(fd);
94 }
95 /* fd < 0? Ah, what the heck. We'll just take whatever was on the
96 * stack... */
97
98 arc4_addrandom(as, (void *) &rdat, sizeof(rdat));
99}
100
101static inline u_int8_t
102arc4_getbyte(as)
103 struct arc4_stream *as;
104{
105 u_int8_t si, sj;
106
107 as->i = (as->i + 1);
108 si = as->s[as->i];
109 as->j = (as->j + si);
110 sj = as->s[as->j];
111 as->s[as->i] = sj;
112 as->s[as->j] = si;
113 return (as->s[(si + sj) & 0xff]);
114}
115
116static inline u_int32_t
117arc4_getword(as)
118 struct arc4_stream *as;
119{
120 u_int32_t val;
121 val = arc4_getbyte(as) << 24;
122 val |= arc4_getbyte(as) << 16;
123 val |= arc4_getbyte(as) << 8;
124 val |= arc4_getbyte(as);
125 return val;
126}
127
128void
129arc4random_stir()
130{
131 if (!rs_initialized) {
132 arc4_init(&rs);
133 rs_initialized = 1;
134 }
135 arc4_stir(&rs);
136}
137
138void
139arc4random_addrandom(dat, datlen)
140 u_char *dat;
141 int datlen;
142{
143 if (!rs_initialized)
144 arc4random_stir();
145 arc4_addrandom(&rs, dat, datlen);
146}
147
148u_int32_t
149arc4random()
150{
151 if (!rs_initialized)
152 arc4random_stir();
153 return arc4_getword(&rs);
154}
155
156#if 0
157/*-------- Test code for i386 --------*/
158#include <stdio.h>
159#include <machine/pctr.h>
160int
161main(int argc, char **argv)
162{
163 const int iter = 1000000;
164 int i;
165 pctrval v;
166
167 v = rdtsc();
168 for (i = 0; i < iter; i++)
169 arc4random();
170 v = rdtsc() - v;
171 v /= iter;
172
173 printf("%qd cycles\n", v);
174}
175#endif