diff options
-rw-r--r-- | lib/libc/gen/Makefile.inc | 11 | ||||
-rw-r--r-- | lib/libc/gen/arc4random.3 | 83 | ||||
-rw-r--r-- | lib/libc/gen/arc4random.c | 172 |
3 files changed, 261 insertions, 5 deletions
diff --git a/lib/libc/gen/Makefile.inc b/lib/libc/gen/Makefile.inc index e5f7a28..b223d9a 100644 --- a/lib/libc/gen/Makefile.inc +++ b/lib/libc/gen/Makefile.inc @@ -1,11 +1,11 @@ # @(#)Makefile.inc 8.6 (Berkeley) 5/4/95 -# $Id: Makefile.inc,v 1.33 1997/05/03 03:49:54 jb Exp $ +# $Id: Makefile.inc,v 1.34 1997/05/30 20:53:13 phk Exp $ # machine-independent gen sources .PATH: ${.CURDIR}/../libc/${MACHINE}/gen ${.CURDIR}/../libc/gen -SRCS+= alarm.c assert.c clock.c closedir.c config.c confstr.c crypt.c \ - ctermid.c daemon.c devname.c disklabel.c err.c errlst.c \ +SRCS+= alarm.c arc4random.c assert.c clock.c closedir.c config.c confstr.c \ + crypt.c ctermid.c daemon.c devname.c disklabel.c err.c errlst.c \ exec.c fnmatch.c frexp.c fstab.c fts.c getbootfile.c getbsize.c \ getcap.c getcwd.c getdomainname.c getgrent.c getgrouplist.c \ gethostname.c getloadavg.c getlogin.c getmntinfo.c getnetgrent.c \ @@ -39,8 +39,8 @@ errlst.o errlst.po: # Only build man pages with libc. .if ${LIB} == "c" -MAN3+= gen/alarm.3 gen/clock.3 gen/confstr.3 gen/config_open.3 \ - gen/crypt.3 gen/ctermid.3 \ +MAN3+= gen/alarm.3 gen/arc4random.3 gen/clock.3 gen/confstr.3 \ + gen/config_open.3 gen/crypt.3 gen/ctermid.3 \ gen/daemon.3 gen/devname.3 gen/directory.3 gen/err.3 gen/exec.3 \ gen/fnmatch.3 gen/frexp.3 gen/fts.3 gen/getbsize.3 gen/getbootfile.3 \ gen/getcap.3 gen/getcwd.3 gen/getdiskbyname.3 gen/getdomainname.3 \ @@ -61,6 +61,7 @@ MAN3+= gen/alarm.3 gen/clock.3 gen/confstr.3 gen/config_open.3 \ gen/times.3 gen/timezone.3 gen/ttyname.3 gen/tzset.3 gen/ualarm.3 \ gen/uname.3 gen/unvis.3 gen/usleep.3 gen/utime.3 gen/valloc.3 gen/vis.3 +MLINKS+=arc4random.3 arc4random_stir.3 arc4random.3 arc4random_addrandom.3 MLINKS+=config_open.3 config_next.3 config_open.3 config_close.3 \ config_open.3 config_skip.3 MLINKS+=crypt.3 encrypt.3 crypt.3 setkey.3 crypt.3 des_setkey.3 \ diff --git a/lib/libc/gen/arc4random.3 b/lib/libc/gen/arc4random.3 new file mode 100644 index 0000000..42bb413 --- /dev/null +++ b/lib/libc/gen/arc4random.3 @@ -0,0 +1,83 @@ +.\" $OpenBSD: arc4random.3,v 1.2 1997/04/27 22:40:25 angelos Exp $ +.\" Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by Niels Provos. +.\" 4. The name of the author may not be used to endorse or promote products +.\" derived from this software without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" Manual page, using -mandoc macros +.\" +.Dd April 15, 1997 +.Dt ARC4RANDOM 3 +.Os +.Sh NAME +.Nm arc4random, +.Nm arc4random_stir, +.Nm arc4random_addrandom +.Nd arc4 random number generator. +.Sh SYNOPSIS +.Fd #include <stdlib.h> +.Ft u_int32_t +.Fn arc4random "void" +.Ft void +.Fn arc4random_stir "void" +.Ft void +.Fn arc4random_addrandom "u_char *dat" "int datlen" +.Sh DESCRIPTION +The +.Fn arc4random +function uses the key stream generator employed by the +arc4 cipher, which uses 8*8 8 bit S-Boxes. The S-Boxes +can be in about +.if t 2\u\s71700\s10\d +.if n (2**1700) +states. +.Pp +The +.Fn arc4random_stir +function reads data from +.Pa /dev/urandom +and uses it to permutate the S-Boxes via +.Fn arc4random_addrandom . +.Pp +There is no need to call +.Fn arc4random_stir +before using +.Fn arc4random , +since +.Fn arc4random +automatically initalizes itself. +.Sh SEE ALSO +.Xr rand 3 , +.Xr random 3 , +.Xr srandomdev 3 +.Sh HISTORY +.Pa RC4 +has been designed by RSA Data Security, Inc. It was posted anonymously +to the USENET and was confirmed to be equivalent by several sources who +had access to the original cipher. Since +.Pa RC4 +used to be a trade secret, the cipher is now refered to as +.Pa ARC4 . diff --git a/lib/libc/gen/arc4random.c b/lib/libc/gen/arc4random.c new file mode 100644 index 0000000..b9f8a48 --- /dev/null +++ b/lib/libc/gen/arc4random.c @@ -0,0 +1,172 @@ +/* $Id: arc4random.c,v 1.1 1996/12/28 06:33:01 dm Exp $ */ + +/* + * Arc4 random number generator for OpenBSD. + * Copyright 1996 David Mazieres <dm@lcs.mit.edu>. + * + * Modification and redistribution in source and binary forms is + * permitted provided that due credit is given to the author and the + * OpenBSD project (for instance by leaving this copyright notice + * intact). + */ + +/* + * This code is derived from section 17.1 of Applied Cryptography, + * second edition, which describes a stream cipher allegedly + * compatible with RSA Labs "RC4" cipher (the actual description of + * which is a trade secret). The same algorithm is used as a stream + * cipher called "arcfour" in Tatu Ylonen's ssh package. + * + * Here the stream cipher has been modified always to include the time + * when initializing the state. That makes it impossible to + * regenerate the same random sequence twice, so this can't be used + * for encryption, but will generate good random numbers. + * + * RC4 is a registered trademark of RSA Laboratories. + */ + +#include <stdlib.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/time.h> + +struct arc4_stream { + u_int8_t i; + u_int8_t j; + u_int8_t s[256]; +}; + +static int rs_initialized; +static struct arc4_stream rs; + +static inline void +arc4_init(as) + struct arc4_stream *as; +{ + int n; + + for (n = 0; n < 256; n++) + as->s[n] = n; + as->i = 0; + as->j = 0; +} + +static inline void +arc4_addrandom(as, dat, datlen) + struct arc4_stream *as; + u_char *dat; + int datlen; +{ + int n; + u_int8_t si; + + as->i--; + for (n = 0; n < 256; n++) { + as->i = (as->i + 1); + si = as->s[as->i]; + as->j = (as->j + si + dat[n % datlen]); + as->s[as->i] = as->s[as->j]; + as->s[as->j] = si; + } +} + +static void +arc4_stir(as) + struct arc4_stream *as; +{ + int fd; + struct { + struct timeval tv; + pid_t pid; + u_int8_t rnd[128 - sizeof(struct timeval) - sizeof(pid_t)]; + } rdat; + + gettimeofday(&rdat.tv, NULL); + rdat.pid = getpid(); + fd = open("/dev/urandom", O_RDONLY, 0); + if (fd >= 0) { + (void) read(fd, rdat.rnd, sizeof(rdat.rnd)); + close(fd); + } + /* fd < 0? Ah, what the heck. We'll just take whatever was on the + * stack... */ + + arc4_addrandom(as, (void *) &rdat, sizeof(rdat)); +} + +static inline u_int8_t +arc4_getbyte(as) + struct arc4_stream *as; +{ + u_int8_t si, sj; + + as->i = (as->i + 1); + si = as->s[as->i]; + as->j = (as->j + si); + sj = as->s[as->j]; + as->s[as->i] = sj; + as->s[as->j] = si; + return (as->s[(si + sj) & 0xff]); +} + +static inline u_int32_t +arc4_getword(as) + struct arc4_stream *as; +{ + u_int32_t val; + val = arc4_getbyte(as) << 24; + val |= arc4_getbyte(as) << 16; + val |= arc4_getbyte(as) << 8; + val |= arc4_getbyte(as); + return val; +} + +void +arc4random_stir() +{ + if (!rs_initialized) { + arc4_init(&rs); + rs_initialized = 1; + } + arc4_stir(&rs); +} + +void +arc4random_addrandom(dat, datlen) + u_char *dat; + int datlen; +{ + if (!rs_initialized) + arc4random_stir(); + arc4_addrandom(&rs, dat, datlen); +} + +u_int32_t +arc4random() +{ + if (!rs_initialized) + arc4random_stir(); + return arc4_getword(&rs); +} + +#if 0 +/*-------- Test code for i386 --------*/ +#include <stdio.h> +#include <machine/pctr.h> +int +main(int argc, char **argv) +{ + const int iter = 1000000; + int i; + pctrval v; + + v = rdtsc(); + for (i = 0; i < iter; i++) + arc4random(); + v = rdtsc() - v; + v /= iter; + + printf("%qd cycles\n", v); +} +#endif |