+++ /dev/null
-Submitted By: Robert Connolly <robert at linuxfromscratch dot org> (ashes)
-Date: 2006-01-01
-Initial Package Version: 2.3.6
-Upstream Status: Not submitted
-Origin: http://www.openbsd.org/cgi-bin/cvsweb/src/lib/libc/crypt/arc4random.c
-Description: This patch adds the arc4random() and arc4randomII() functions
-to Glibc, and hooks so mktemp(3) can use arc4randomII().
-
-Also see:
-http://www.linuxfromscratch.org/hlfs/
-http://www.linuxfromscratch.org/hints/downloads/files/entropy.txt
-
-diff -Naur glibc-2.3.6.orig/manual/arc4random.3 glibc-2.3.6/manual/arc4random.3
---- glibc-2.3.6.orig/manual/arc4random.3 1970-01-01 00:00:00.000000000 +0000
-+++ glibc-2.3.6/manual/arc4random.3 2006-01-01 07:48:48.000000000 +0000
-@@ -0,0 +1,74 @@
-+.TH ARC4RANDOM 3 "February 11, 2005"
-+.SH NAME
-+arc4random - arc4 random number generator
-+.SH SYNOPSIS
-+.nf
-+.B #include <stdlib.h>
-+.sp
-+.I u_int32_t
-+.B arc4random(void);
-+.sp
-+.I u_int32_t
-+.B arc4randomII(void);
-+.fi
-+.SH DESCRIPTION
-+The \fBarc4random()\fP function generates a pseudo-random number using the
-+ARC4 cipher key stream generator. ARCFOUR uses 8*8 8 bit S-Boxes, and can
-+be in about (2**1700) states.
-+
-+The \fBarc4random()\fP function is seeded automatically from /dev/urandom,
-+or from sysctl \fBurandom\fP if /dev/urandom is not accessible (chroot), or from
-+sysctl random.uuid if sysctl \fBurandom\fP is not accessible. \fBgettimeofday(2)\fP
-+is always included when initializing the state of \fBarc4random()\fP, this makes
-+it impossible to generate the same random sequence twice. \fBarc4random()\fP
-+is intended to be safe to use with encryption software to provide entropy.
-+
-+The \fBarc4randomII()\fP function is identical to \fBarc4random()\fP except
-+that \fBarc4randomII()\fP is seeded automatically from /dev/erandom, and
-+sysctl erandom. \fBarc4randomII()\fP is NOT intended for cryptography, but is
-+ideal for \fBmktemp(3)\fP, and other functions with a short lifespan.
-+\fBarc4randomII()\fP and erandom do not consume any kernel entropy.
-+
-+Sysctl urandom, and erandom require a modified kernel. See:
-+http://www.linuxfromscratch.org/hlfs/
-+
-+.SH EXAMPLES
-+.TP
-+Return a random number between 0 and 100.
-+.sp
-+arc4random() % 100;
-+.TP
-+Return any random number.
-+.sp
-+arc4random();
-+.TP
-+.nf
-+Sample program; this will display a number between 0 and 65536.
-+
-+#include <stdlib.h>
-+#include <stdio.h>
-+
-+int main(void) {
-+ int random_number;
-+ random_number = arc4random() % 65536;
-+ printf("%d\n", random_number);
-+ return 0;
-+}
-+.fi
-+.SH "SEE ALSO"
-+.BR random (3),
-+.BR gettimeofday (2),
-+.BR mktemp (3)
-+
-+.SH HISTORY
-+An algorithm called RC4 was designed by RSA Data Security, Inc. It was
-+considered a trade secret, but not trademarked. Because it was a trade
-+secret, it obviously could not be patented. A clone of this was posted
-+anonymously to USENET and confirmed to be equivalent by several sources
-+who had access to the original cipher. Because of the trade secret situation,
-+RSA Data Security, Inc. can do nothing about the release of the
-+ARC4 algorithm. Since RC4 used to be a trade secret, the cipher is now
-+referred to as ARC4 (Another RC4).
-+
-+These functions first appeared in OpenBSD 2.1.
-+
-diff -Naur glibc-2.3.6.orig/stdlib/Makefile glibc-2.3.6/stdlib/Makefile
---- glibc-2.3.6.orig/stdlib/Makefile 2005-02-16 11:23:58.000000000 +0000
-+++ glibc-2.3.6/stdlib/Makefile 2006-01-01 07:48:48.000000000 +0000
-@@ -27,7 +27,7 @@
-
- routines := \
- atof atoi atol atoll \
-- abort \
-+ abort arc4random arc4randomII \
- bsearch qsort msort \
- getenv putenv setenv secure-getenv \
- exit on_exit atexit cxa_atexit cxa_finalize old_atexit \
-diff -Naur glibc-2.3.6.orig/stdlib/Versions glibc-2.3.6/stdlib/Versions
---- glibc-2.3.6.orig/stdlib/Versions 2004-05-03 21:25:53.000000000 +0000
-+++ glibc-2.3.6/stdlib/Versions 2006-01-01 07:50:28.000000000 +0000
-@@ -11,6 +11,8 @@
-
- # a*
- a64l; abort; abs; atexit; atof; atoi; atol; atoll;
-+ arc4random_stir; arc4random_addrandom; arc4random;
-+ arc4random_stirII; arc4random_addrandomII; arc4randomII;
-
- # b*
- bsearch;
-diff -Naur glibc-2.3.6.orig/stdlib/arc4random.c glibc-2.3.6/stdlib/arc4random.c
---- glibc-2.3.6.orig/stdlib/arc4random.c 1970-01-01 00:00:00.000000000 +0000
-+++ glibc-2.3.6/stdlib/arc4random.c 2006-01-01 07:48:48.000000000 +0000
-@@ -0,0 +1,205 @@
-+/*
-+ * 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 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.
-+ */
-+
-+/*
-+ * Modified by Robert Connolly from OpenBSD lib/libc/crypt/arc4random.c v1.11.
-+ * This is arc4random(3) using urandom.
-+ */
-+
-+#include <fcntl.h>
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <sys/types.h>
-+#include <sys/param.h>
-+#include <sys/time.h>
-+#include <sys/sysctl.h>
-+
-+#ifdef __GNUC__
-+#define inline __inline
-+#else /* !__GNUC__ */
-+#define inline
-+#endif /* !__GNUC__ */
-+
-+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 pid_t arc4_stir_pid;
-+
-+static inline u_int8_t arc4_getbyte(struct arc4_stream *);
-+
-+static inline void
-+arc4_init(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(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;
-+ }
-+ as->j = as->i;
-+}
-+
-+static void
-+arc4_stir(struct arc4_stream *as)
-+{
-+ int n, fd;
-+ struct {
-+ struct timeval tv;
-+ u_int rnd[(128 - sizeof(struct timeval)) / sizeof(u_int)];
-+ } rdat;
-+
-+ gettimeofday(&rdat.tv, NULL);
-+
-+ /* /dev/urandom is a multithread interface, sysctl is not. */
-+ /* Try to use /dev/urandom before sysctl. */
-+ fd = open("/dev/urandom", O_RDONLY);
-+ if (fd != -1) {
-+ read(fd, rdat.rnd, sizeof(rdat.rnd));
-+ close(fd);
-+ }
-+
-+#if defined(SYSCTL_URANDOM)
-+ else {
-+ /* /dev/urandom failed? Maybe we're in a chroot. */
-+ int mib[]={CTL_KERN, KERN_RANDOM, RANDOM_URANDOM};
-+ u_int i;
-+ size_t len;
-+
-+ for (i = 0; i < sizeof(rdat.rnd) / sizeof(u_int); i ++) {
-+ len = sizeof(u_int);
-+ if (sysctl(mib, 3, &rdat.rnd[i], &len, NULL, 0) == -1)
-+ break;
-+ }
-+ if (i < sizeof(rdat.rnd) / 4) {
-+ /* Sysctl urandom failed? Maybe we're running a vanilla kernel. */
-+ mib[2] = RANDOM_UUID;
-+ for (i = 0; i < sizeof(rdat.rnd) / sizeof(u_int); i ++) {
-+ len = sizeof(u_int);
-+ if (sysctl(mib, 3, &rdat.rnd[i], &len, NULL, 0) == -1)
-+ break;
-+ }
-+ }
-+ }
-+#endif
-+
-+ arc4_stir_pid = getpid();
-+ /*
-+ * Time to give up. If no entropy could be found then we will just
-+ * use gettimeofday.
-+ */
-+ arc4_addrandom(as, (void *)&rdat, sizeof(rdat));
-+
-+ /*
-+ * Discard early keystream, as per recommendations in:
-+ * http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps
-+ * We discard 256 words. A long word is 4 bytes.
-+ */
-+ for (n = 0; n < 256 * 4; n ++)
-+ arc4_getbyte(as);
-+}
-+
-+static inline u_int8_t
-+arc4_getbyte(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(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(void)
-+{
-+ if (!rs_initialized) {
-+ arc4_init(&rs);
-+ rs_initialized = 1;
-+ }
-+ arc4_stir(&rs);
-+}
-+
-+void
-+arc4random_addrandom(u_char *dat, int datlen)
-+{
-+ if (!rs_initialized)
-+ arc4random_stir();
-+ arc4_addrandom(&rs, dat, datlen);
-+}
-+
-+u_int32_t
-+arc4random(void)
-+{
-+ if (!rs_initialized || arc4_stir_pid != getpid())
-+ arc4random_stir();
-+ return arc4_getword(&rs);
-+}
-+
-+#if 0
-+/*-------- Test code --------*/
-+#include <stdlib.h>
-+#include <stdio.h>
-+
-+int main(void) {
-+ int random_number;
-+ random_number = arc4random() % 65536;
-+ printf("A random number between 0 and 65536 is %d\n", random_number);
-+ return 0;
-+}
-+#endif
-diff -Naur glibc-2.3.6.orig/stdlib/arc4randomII.c glibc-2.3.6/stdlib/arc4randomII.c
---- glibc-2.3.6.orig/stdlib/arc4randomII.c 1970-01-01 00:00:00.000000000 +0000
-+++ glibc-2.3.6/stdlib/arc4randomII.c 2006-01-01 07:48:48.000000000 +0000
-@@ -0,0 +1,196 @@
-+/*
-+ * 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 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.
-+ */
-+
-+/*
-+ * Modified by Robert Connolly from OpenBSD lib/libc/crypt/arc4random.c v1.11.
-+ * This is arc4randomII(3) using erandom.
-+ */
-+
-+#include <fcntl.h>
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <sys/types.h>
-+#include <sys/param.h>
-+#include <sys/time.h>
-+#include <sys/sysctl.h>
-+
-+#ifdef __GNUC__
-+#define inline __inline
-+#else /* !__GNUC__ */
-+#define inline
-+#endif /* !__GNUC__ */
-+
-+struct arc4_streamII {
-+ u_int8_t i;
-+ u_int8_t j;
-+ u_int8_t s[256];
-+};
-+
-+static int rs_initializedII;
-+static struct arc4_streamII rs;
-+static pid_t arc4_stir_pidII;
-+
-+static inline u_int8_t arc4_getbyteII(struct arc4_streamII *);
-+
-+static inline void
-+arc4_initII(struct arc4_streamII *as)
-+{
-+ int n;
-+
-+ for (n = 0; n < 256; n++)
-+ as->s[n] = n;
-+ as->i = 0;
-+ as->j = 0;
-+}
-+
-+static inline void
-+arc4_addrandomII(struct arc4_streamII *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;
-+ }
-+ as->j = as->i;
-+}
-+
-+static void
-+arc4_stirII(struct arc4_streamII *as)
-+{
-+ int n, fd;
-+ struct {
-+ struct timeval tv;
-+ u_int rnd[(128 - sizeof(struct timeval)) / sizeof(u_int)];
-+ } rdat;
-+
-+ gettimeofday(&rdat.tv, NULL);
-+
-+ /* /dev/urandom is a multithread interface, sysctl is not. */
-+ /* Try to use /dev/urandom before sysctl. */
-+ fd = open("/dev/erandom", O_RDONLY);
-+ if (fd != -1) {
-+ read(fd, rdat.rnd, sizeof(rdat.rnd));
-+ close(fd);
-+ }
-+
-+#if defined(SYSCTL_ERANDOM)
-+ else {
-+ /* /dev/urandom failed? Maybe we're in a chroot. */
-+ int mib[]={CTL_KERN, KERN_RANDOM, RANDOM_ERANDOM};
-+ u_int i;
-+ size_t len;
-+
-+ for (i = 0; i < sizeof(rdat.rnd) / sizeof(u_int); i++) {
-+ len = sizeof(u_int);
-+ if (sysctl(mib, 3, &rdat.rnd[i], &len, NULL, 0) == -1)
-+ break;
-+ }
-+ }
-+#endif
-+
-+ arc4_stir_pidII = getpid();
-+ /*
-+ * Time to give up. If no entropy could be found then we will just
-+ * use gettimeofday.
-+ */
-+ arc4_addrandomII(as, (void *)&rdat, sizeof(rdat));
-+
-+ /*
-+ * Discard early keystream, as per recommendations in:
-+ * http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps
-+ * We discard 256 words. A long word is 4 bytes.
-+ */
-+ for (n = 0; n < 256 * 4; n ++)
-+ arc4_getbyteII(as);
-+}
-+
-+static inline u_int8_t
-+arc4_getbyteII(struct arc4_streamII *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_getwordII(struct arc4_streamII *as)
-+{
-+ u_int32_t val;
-+ val = arc4_getbyteII(as) << 24;
-+ val |= arc4_getbyteII(as) << 16;
-+ val |= arc4_getbyteII(as) << 8;
-+ val |= arc4_getbyteII(as);
-+ return val;
-+}
-+
-+void
-+arc4random_stirII(void)
-+{
-+ if (!rs_initializedII) {
-+ arc4_initII(&rs);
-+ rs_initializedII = 1;
-+ }
-+ arc4_stirII(&rs);
-+}
-+
-+void
-+arc4random_addrandomII(u_char *dat, int datlen)
-+{
-+ if (!rs_initializedII)
-+ arc4random_stirII();
-+ arc4_addrandomII(&rs, dat, datlen);
-+}
-+
-+u_int32_t
-+arc4randomII(void)
-+{
-+ if (!rs_initializedII || arc4_stir_pidII != getpid())
-+ arc4random_stirII();
-+ return arc4_getwordII(&rs);
-+}
-+
-+#if 0
-+/*-------- Test code --------*/
-+#include <stdlib.h>
-+#include <stdio.h>
-+
-+int main(void) {
-+ int random_number;
-+ random_number = arc4randomII() % 65536;
-+ printf("A random number between 0 and 65536 is %d\n", random_number);
-+ return 0;
-+}
-+#endif
-diff -Naur glibc-2.3.6.orig/stdlib/stdlib.h glibc-2.3.6/stdlib/stdlib.h
---- glibc-2.3.6.orig/stdlib/stdlib.h 2005-07-18 01:15:30.000000000 +0000
-+++ glibc-2.3.6/stdlib/stdlib.h 2006-01-01 07:48:48.000000000 +0000
-@@ -572,6 +572,15 @@
- extern int lcong48_r (unsigned short int __param[7],
- struct drand48_data *__buffer)
- __THROW __nonnull ((1, 2));
-+
-+#define LIBC_HAS_ARC4RANDOM
-+u_int32_t arc4random(void);
-+void arc4random_stir(void);
-+void arc4random_addrandom(unsigned char *, int);
-+u_int32_t arc4randomII(void);
-+void arc4random_stirII(void);
-+void arc4random_addrandomII(unsigned char *, int);
-+
- # endif /* Use misc. */
- #endif /* Use SVID or X/Open. */