diff -Naur glibc-2.4.orig/include/features.h glibc-2.4/include/features.h --- glibc-2.4.orig/include/features.h 2006-01-05 12:25:35.000000000 +0000 +++ glibc-2.4/include/features.h 2006-06-04 19:48:44.000000000 +0000 @@ -338,6 +338,7 @@ # define __USE_EXTERN_INLINES 1 #endif +# define HAVE_ARC4RANDOM /* This is here only because every header file already includes this one. Get the definitions of all the appropriate `__stub_FUNCTION' symbols. diff -Naur glibc-2.4.orig/manual/arc4random.3 glibc-2.4/manual/arc4random.3 --- glibc-2.4.orig/manual/arc4random.3 1970-01-01 00:00:00.000000000 +0000 +++ glibc-2.4/manual/arc4random.3 2006-06-04 20:01:59.000000000 +0000 @@ -0,0 +1,62 @@ +.TH ARC4RANDOM 3 "June 4, 2006" +.SH NAME +arc4random - arcfour random number generator +.SH SYNOPSIS +.nf +.B #include +.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(3)\fP function is seeded automatically from \fBurandom(4)\fP. +If \fBurandom(4)\fP is not available then \fBgettimeofday(2)\fP is used. This +makes \fBarc4random(3)\fP more dependable than using urandom directly. + +.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 +#include + +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). + +This functions first appeared in OpenBSD 2.1. + diff -Naur glibc-2.4.orig/stdlib/Makefile glibc-2.4/stdlib/Makefile --- glibc-2.4.orig/stdlib/Makefile 2006-02-28 07:06:04.000000000 +0000 +++ glibc-2.4/stdlib/Makefile 2006-06-04 19:06:34.000000000 +0000 @@ -30,7 +30,7 @@ routines := \ atof atoi atol atoll \ - abort \ + abort arc4random \ bsearch qsort msort \ getenv putenv setenv secure-getenv \ exit on_exit atexit cxa_atexit cxa_finalize old_atexit \ diff -Naur glibc-2.4.orig/stdlib/Versions glibc-2.4/stdlib/Versions --- glibc-2.4.orig/stdlib/Versions 2004-05-03 21:25:53.000000000 +0000 +++ glibc-2.4/stdlib/Versions 2006-06-04 20:01:20.000000000 +0000 @@ -11,6 +11,7 @@ # a* a64l; abort; abs; atexit; atof; atoi; atol; atoll; + arc4random_stir; arc4random_addrandom; arc4random; # b* bsearch; diff -Naur glibc-2.4.orig/stdlib/arc4random.c glibc-2.4/stdlib/arc4random.c --- glibc-2.4.orig/stdlib/arc4random.c 1970-01-01 00:00:00.000000000 +0000 +++ glibc-2.4/stdlib/arc4random.c 2006-06-04 20:02:57.000000000 +0000 @@ -0,0 +1,273 @@ +/* Modified for Linux - Robert Connolly 2006/06/03 */ +/* $OpenBSD: arc4random.c,v 1.15 2005/11/30 07:51:02 otto Exp $ */ + +/* + * Copyright (c) 1996, David Mazieres + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Arc4 random number generator for OpenBSD. + * + * 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 +#include +#include +#include +#include +#include +#if defined(ARC4RANDOM_USES_SYSCTL_ERANDOM) || !defined(__UCLIBC__) +#include +#endif + +#ifdef __UCLIBC__ +libc_hidden_proto(open) +libc_hidden_proto(read) +libc_hidden_proto(close) +libc_hidden_proto(gettimeofday) +#endif + +#if !defined(__UCLIBC__) && defined(_LIBC) && defined(__GLIBC__) +#define open __open +#define read __read +#define close __close +#define getpid __getpid +#define gettimeofday __gettimeofday +#endif + +#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 int arc4_count; + +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) +{ +/* + * Erandom (Frandom's daughter) is a pseudo random number generator which + * uses no kernel entropy during use, but is seeded by Frandom which is + * seeded by kernel entropy. Erandom's initial seed is available only to + * root/the-kernel, making Erandom's output safe for security applications. + * Thanks to Eli Billauer for the Erandom + * kernel driver. Also see + */ + +/* + * Erandom is available as a sysctl value. Sysctl has the advantage of + * working from inside a chroot. Although sysctl is a single-threaded + * interface, the operation of obtaining a value from sysctl is so quick + * that there is little-to-no wait time for processes, and peformance is + * excelent. + * + * SYSCTL_ERANDOM* is defined from . This requires a + * modified kernel. Also see: + * + */ + +/* The vanilla Erandom sysctl provides 16 bytes. */ +/* The modified fat version of Erandom sysctl provides 256 bytes. */ + + int i, fd; + u_char rnd[128]; + +/* If SYSCTL_ERANDOM* is defined, use it first. */ +#if !defined(__UCLIBC__) || defined(ARC4RANDOM_USES_SYSCTL_ERANDOM) +#if defined(SYSCTL_ERANDOM) || defined(SYSCTL_ERANDOM256) + int mib[]={CTL_KERN, KERN_RANDOM, RANDOM_ERANDOM}; + size_t len; + len = sizeof(rnd); +#endif +#ifdef SYSCTL_ERANDOM256 + /* Fill the buffer in one shot. */ + if (sysctl(mib, 3, rnd, &len, NULL, 0) == -1) { +#endif +#ifdef SYSCTL_ERANDOM + /* Fill the buffer in eight shots. */ + for (i = 0; i < sizeof(rnd) / sizeof(u_int); i ++) { + len = sizeof(u_int); + if (sysctl(mib, 3, rnd[i], &len, NULL, 0) == -1) { +#endif +#endif /* !__UCLIBC__ || ARC4RANDOM_USES_SYSCTL_ERANDOM */ +#if !defined(__UCLIBC__) || defined(UCLIBC_USES_ERANDOM) + /* If sysctl erandom did not work, try /dev/erandom. */ + fd = open("/dev/erandom", O_RDONLY); + if (fd != -1) { + read(fd, rnd, sizeof(rnd)); + close(fd); + } + else { +#endif + /* If /dev/erandom did not work try /dev/urandom. */ + fd = open("/dev/urandom", O_RDONLY); + if (fd != -1) { + read(fd, rnd, sizeof(rnd)); + close(fd); + } + else { + /* Erandom and Urandom failed? Use the time. */ + struct { + struct timeval tv; + u_int rnd[(128 - sizeof(struct timeval)) + / sizeof(u_int)]; + } rdat; + gettimeofday(&rdat.tv, NULL); + } +#if !defined(__UCLIBC__) || defined(UCLIBC_USES_ERANDOM) + } +#endif +#if defined(SYSCTL_ERANDOM) || defined(SYSCTL_ERANDOM256) + } +#endif + + arc4_stir_pid = getpid(); + arc4_addrandom(as, rnd, sizeof(rnd)); + + /* + * Throw away the first N words of output, as suggested in the + * paper "Weaknesses in the Key Scheduling Algorithm of RC4" + * by Fluher, Mantin, and Shamir. + * http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps + * N = 256 in our case. + */ + + for (i = 0; i < 256; i++) + (void)arc4_getbyte(as); + arc4_count = 400000; +} + +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; +} + +#ifdef __UCLIBC__ +libc_hidden_proto(arc4random_stir) +#endif +void +arc4random_stir(void) +{ + if (!rs_initialized) { + arc4_init(&rs); + rs_initialized = 1; + } + arc4_stir(&rs); +} +#ifdef __UCLIBC__ +libc_hidden_def(arc4random_stir) +#endif + +void +arc4random_addrandom(u_char *dat, int datlen) +{ + if (!rs_initialized) + arc4random_stir(); + arc4_addrandom(&rs, dat, datlen); +} + +u_int32_t +arc4random(void) +{ + if (--arc4_count == 0 || !rs_initialized || arc4_stir_pid != getpid()) + arc4random_stir(); + return arc4_getword(&rs); +} + +#if 0 +/*-------- Test code --------*/ +/* Output a random number */ +#include +#include + +int main(void) { + int random_number; + random_number = arc4random() % 65536; + printf("%d\n", random_number); + return 0; +} +#endif diff -Naur glibc-2.4.orig/stdlib/stdlib.h glibc-2.4/stdlib/stdlib.h --- glibc-2.4.orig/stdlib/stdlib.h 2006-01-14 12:08:29.000000000 +0000 +++ glibc-2.4/stdlib/stdlib.h 2006-06-04 19:47:59.000000000 +0000 @@ -577,6 +577,15 @@ extern int lcong48_r (unsigned short int __param[7], struct drand48_data *__buffer) __THROW __nonnull ((1, 2)); + +/* arc4random(3) prototypes */ +#ifdef HAVE_ARC4RANDOM +#include +u_int32_t arc4random(void); +void arc4random_stir(void); +void arc4random_addrandom(unsigned char *, int); +#endif + # endif /* Use misc. */ #endif /* Use SVID or X/Open. */ diff -Naur glibc-2.4.orig/sysdeps/posix/tempname.c glibc-2.4/sysdeps/posix/tempname.c --- glibc-2.4.orig/sysdeps/posix/tempname.c 2001-11-27 03:35:06.000000000 +0000 +++ glibc-2.4/sysdeps/posix/tempname.c 2006-06-04 20:05:31.000000000 +0000 @@ -16,6 +16,7 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ + #if HAVE_CONFIG_H # include #endif @@ -258,8 +259,15 @@ /* This is where the Xs start. */ XXXXXX = &tmpl[len - 6]; - /* Get some more or less random data. */ +/* Get real random data. */ +#if !defined(_FEATURES_H) && !defined(HAVE_ARC4RANDOM) +#include /* For HAVE_ARC4RANDOM */ +#endif +#ifdef HAVE_ARC4RANDOM + random_time_bits = arc4random(); +# else #ifdef RANDOM_BITS + /* Get some more or less random data. */ RANDOM_BITS (random_time_bits); #else # if HAVE_GETTIMEOFDAY || _LIBC @@ -272,7 +280,12 @@ random_time_bits = time (NULL); # endif #endif +#endif /* HAVE_ARC4RANDOM */ +# ifdef HAVE_ARC4RANDOM + value += random_time_bits ^ arc4random(); +# else value += random_time_bits ^ __getpid (); +# endif for (count = 0; count < attempts; value += 7777, ++count) {