]> git.ipfire.org Git - people/ms/ipfire-3.x.git/blame - glibc/patches/glibc-2.10.1-arc4random.patch
Move all packages to root.
[people/ms/ipfire-3.x.git] / glibc / patches / glibc-2.10.1-arc4random.patch
CommitLineData
b2ec3c8a
MT
1Submitted By: Robert Connolly <robert at linuxfromscratch dot org> (ashes)
2Date: 2006-01-01
3Initial Package Version: 2.3.6
4Upstream Status: Not submitted
5Origin: http://www.openbsd.org/cgi-bin/cvsweb/src/lib/libc/crypt/arc4random.c
6Description: This patch adds the arc4random() and arc4randomII() functions
7to Glibc, and hooks so mktemp(3) can use arc4randomII().
8
9Also see:
10http://www.linuxfromscratch.org/hlfs/
11http://www.linuxfromscratch.org/hints/downloads/files/entropy.txt
12
13diff -Naur glibc-2.3.6.orig/manual/arc4random.3 glibc-2.3.6/manual/arc4random.3
14--- glibc-2.3.6.orig/manual/arc4random.3 1970-01-01 00:00:00.000000000 +0000
15+++ glibc-2.3.6/manual/arc4random.3 2006-01-01 07:48:48.000000000 +0000
16@@ -0,0 +1,74 @@
17+.TH ARC4RANDOM 3 "February 11, 2005"
18+.SH NAME
19+arc4random - arc4 random number generator
20+.SH SYNOPSIS
21+.nf
22+.B #include <stdlib.h>
23+.sp
24+.I u_int32_t
25+.B arc4random(void);
26+.sp
27+.I u_int32_t
28+.B arc4randomII(void);
29+.fi
30+.SH DESCRIPTION
31+The \fBarc4random()\fP function generates a pseudo-random number using the
32+ARC4 cipher key stream generator. ARCFOUR uses 8*8 8 bit S-Boxes, and can
33+be in about (2**1700) states.
34+
35+The \fBarc4random()\fP function is seeded automatically from /dev/urandom,
36+or from sysctl \fBurandom\fP if /dev/urandom is not accessible (chroot), or from
37+sysctl random.uuid if sysctl \fBurandom\fP is not accessible. \fBgettimeofday(2)\fP
38+is always included when initializing the state of \fBarc4random()\fP, this makes
39+it impossible to generate the same random sequence twice. \fBarc4random()\fP
40+is intended to be safe to use with encryption software to provide entropy.
41+
42+The \fBarc4randomII()\fP function is identical to \fBarc4random()\fP except
43+that \fBarc4randomII()\fP is seeded automatically from /dev/erandom, and
44+sysctl erandom. \fBarc4randomII()\fP is NOT intended for cryptography, but is
45+ideal for \fBmktemp(3)\fP, and other functions with a short lifespan.
46+\fBarc4randomII()\fP and erandom do not consume any kernel entropy.
47+
48+Sysctl urandom, and erandom require a modified kernel. See:
49+http://www.linuxfromscratch.org/hlfs/
50+
51+.SH EXAMPLES
52+.TP
53+Return a random number between 0 and 100.
54+.sp
55+arc4random() % 100;
56+.TP
57+Return any random number.
58+.sp
59+arc4random();
60+.TP
61+.nf
62+Sample program; this will display a number between 0 and 65536.
63+
64+#include <stdlib.h>
65+#include <stdio.h>
66+
67+int main(void) {
68+ int random_number;
69+ random_number = arc4random() % 65536;
70+ printf("%d\n", random_number);
71+ return 0;
72+}
73+.fi
74+.SH "SEE ALSO"
75+.BR random (3),
76+.BR gettimeofday (2),
77+.BR mktemp (3)
78+
79+.SH HISTORY
80+An algorithm called RC4 was designed by RSA Data Security, Inc. It was
81+considered a trade secret, but not trademarked. Because it was a trade
82+secret, it obviously could not be patented. A clone of this was posted
83+anonymously to USENET and confirmed to be equivalent by several sources
84+who had access to the original cipher. Because of the trade secret situation,
85+RSA Data Security, Inc. can do nothing about the release of the
86+ARC4 algorithm. Since RC4 used to be a trade secret, the cipher is now
87+referred to as ARC4 (Another RC4).
88+
89+These functions first appeared in OpenBSD 2.1.
90+
91diff -Naur glibc-2.3.6.orig/stdlib/Makefile glibc-2.3.6/stdlib/Makefile
92--- glibc-2.3.6.orig/stdlib/Makefile 2005-02-16 11:23:58.000000000 +0000
93+++ glibc-2.3.6/stdlib/Makefile 2006-01-01 07:48:48.000000000 +0000
94@@ -27,7 +27,7 @@
95
96 routines := \
97 atof atoi atol atoll \
98- abort \
99+ abort arc4random arc4randomII \
100 bsearch qsort msort \
101 getenv putenv setenv secure-getenv \
102 exit on_exit atexit cxa_atexit cxa_finalize old_atexit \
103diff -Naur glibc-2.3.6.orig/stdlib/Versions glibc-2.3.6/stdlib/Versions
104--- glibc-2.3.6.orig/stdlib/Versions 2004-05-03 21:25:53.000000000 +0000
105+++ glibc-2.3.6/stdlib/Versions 2006-01-01 07:50:28.000000000 +0000
106@@ -11,6 +11,8 @@
107
108 # a*
109 a64l; abort; abs; atexit; atof; atoi; atol; atoll;
110+ arc4random_stir; arc4random_addrandom; arc4random;
111+ arc4random_stirII; arc4random_addrandomII; arc4randomII;
112
113 # b*
114 bsearch;
115diff -Naur glibc-2.3.6.orig/stdlib/arc4random.c glibc-2.3.6/stdlib/arc4random.c
116--- glibc-2.3.6.orig/stdlib/arc4random.c 1970-01-01 00:00:00.000000000 +0000
117+++ glibc-2.3.6/stdlib/arc4random.c 2006-01-01 07:48:48.000000000 +0000
118@@ -0,0 +1,205 @@
119+/*
120+ * Arc4 random number generator for OpenBSD.
121+ * Copyright 1996 David Mazieres <dm@lcs.mit.edu>.
122+ *
123+ * Modification and redistribution in source and binary forms is
124+ * permitted provided that due credit is given to the author and the
125+ * OpenBSD project by leaving this copyright notice intact.
126+ */
127+
128+/*
129+ * This code is derived from section 17.1 of Applied Cryptography,
130+ * second edition, which describes a stream cipher allegedly
131+ * compatible with RSA Labs "RC4" cipher (the actual description of
132+ * which is a trade secret). The same algorithm is used as a stream
133+ * cipher called "arcfour" in Tatu Ylonen's ssh package.
134+ *
135+ * Here the stream cipher has been modified always to include the time
136+ * when initializing the state. That makes it impossible to
137+ * regenerate the same random sequence twice, so this can't be used
138+ * for encryption, but will generate good random numbers.
139+ *
140+ * RC4 is a registered trademark of RSA Laboratories.
141+ */
142+
143+/*
144+ * Modified by Robert Connolly from OpenBSD lib/libc/crypt/arc4random.c v1.11.
145+ * This is arc4random(3) using urandom.
146+ */
147+
148+#include <fcntl.h>
149+#include <stdlib.h>
150+#include <unistd.h>
151+#include <sys/types.h>
152+#include <sys/param.h>
153+#include <sys/time.h>
154+#include <sys/sysctl.h>
155+
156+#ifdef __GNUC__
157+#define inline __inline
158+#else /* !__GNUC__ */
159+#define inline
160+#endif /* !__GNUC__ */
161+
162+struct arc4_stream {
163+ u_int8_t i;
164+ u_int8_t j;
165+ u_int8_t s[256];
166+};
167+
168+static int rs_initialized;
169+static struct arc4_stream rs;
170+static pid_t arc4_stir_pid;
171+
172+static inline u_int8_t arc4_getbyte(struct arc4_stream *);
173+
174+static inline void
175+arc4_init(struct arc4_stream *as)
176+{
177+ int n;
178+
179+ for (n = 0; n < 256; n++)
180+ as->s[n] = n;
181+ as->i = 0;
182+ as->j = 0;
183+}
184+
185+static inline void
186+arc4_addrandom(struct arc4_stream *as, u_char *dat, int datlen)
187+{
188+ int n;
189+ u_int8_t si;
190+
191+ as->i--;
192+ for (n = 0; n < 256; n++) {
193+ as->i = (as->i + 1);
194+ si = as->s[as->i];
195+ as->j = (as->j + si + dat[n % datlen]);
196+ as->s[as->i] = as->s[as->j];
197+ as->s[as->j] = si;
198+ }
199+ as->j = as->i;
200+}
201+
202+static void
203+arc4_stir(struct arc4_stream *as)
204+{
205+ int n, fd;
206+ struct {
207+ struct timeval tv;
208+ u_int rnd[(128 - sizeof(struct timeval)) / sizeof(u_int)];
209+ } rdat;
210+
211+ gettimeofday(&rdat.tv, NULL);
212+
213+ /* /dev/urandom is a multithread interface, sysctl is not. */
214+ /* Try to use /dev/urandom before sysctl. */
215+ fd = open("/dev/urandom", O_RDONLY);
216+ if (fd != -1) {
217+ read(fd, rdat.rnd, sizeof(rdat.rnd));
218+ close(fd);
219+ }
220+
221+#if defined(SYSCTL_URANDOM)
222+ else {
223+ /* /dev/urandom failed? Maybe we're in a chroot. */
224+ int mib[]={CTL_KERN, KERN_RANDOM, RANDOM_URANDOM};
225+ u_int i;
226+ size_t len;
227+
228+ for (i = 0; i < sizeof(rdat.rnd) / sizeof(u_int); i ++) {
229+ len = sizeof(u_int);
230+ if (sysctl(mib, 3, &rdat.rnd[i], &len, NULL, 0) == -1)
231+ break;
232+ }
233+ if (i < sizeof(rdat.rnd) / 4) {
234+ /* Sysctl urandom failed? Maybe we're running a vanilla kernel. */
235+ mib[2] = RANDOM_UUID;
236+ for (i = 0; i < sizeof(rdat.rnd) / sizeof(u_int); i ++) {
237+ len = sizeof(u_int);
238+ if (sysctl(mib, 3, &rdat.rnd[i], &len, NULL, 0) == -1)
239+ break;
240+ }
241+ }
242+ }
243+#endif
244+
245+ arc4_stir_pid = getpid();
246+ /*
247+ * Time to give up. If no entropy could be found then we will just
248+ * use gettimeofday.
249+ */
250+ arc4_addrandom(as, (void *)&rdat, sizeof(rdat));
251+
252+ /*
253+ * Discard early keystream, as per recommendations in:
254+ * http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps
255+ * We discard 256 words. A long word is 4 bytes.
256+ */
257+ for (n = 0; n < 256 * 4; n ++)
258+ arc4_getbyte(as);
259+}
260+
261+static inline u_int8_t
262+arc4_getbyte(struct arc4_stream *as)
263+{
264+ u_int8_t si, sj;
265+
266+ as->i = (as->i + 1);
267+ si = as->s[as->i];
268+ as->j = (as->j + si);
269+ sj = as->s[as->j];
270+ as->s[as->i] = sj;
271+ as->s[as->j] = si;
272+ return (as->s[(si + sj) & 0xff]);
273+}
274+
275+static inline u_int32_t
276+arc4_getword(struct arc4_stream *as)
277+{
278+ u_int32_t val;
279+ val = arc4_getbyte(as) << 24;
280+ val |= arc4_getbyte(as) << 16;
281+ val |= arc4_getbyte(as) << 8;
282+ val |= arc4_getbyte(as);
283+ return val;
284+}
285+
286+void
287+arc4random_stir(void)
288+{
289+ if (!rs_initialized) {
290+ arc4_init(&rs);
291+ rs_initialized = 1;
292+ }
293+ arc4_stir(&rs);
294+}
295+
296+void
297+arc4random_addrandom(u_char *dat, int datlen)
298+{
299+ if (!rs_initialized)
300+ arc4random_stir();
301+ arc4_addrandom(&rs, dat, datlen);
302+}
303+
304+u_int32_t
305+arc4random(void)
306+{
307+ if (!rs_initialized || arc4_stir_pid != getpid())
308+ arc4random_stir();
309+ return arc4_getword(&rs);
310+}
311+
312+#if 0
313+/*-------- Test code --------*/
314+#include <stdlib.h>
315+#include <stdio.h>
316+
317+int main(void) {
318+ int random_number;
319+ random_number = arc4random() % 65536;
320+ printf("A random number between 0 and 65536 is %d\n", random_number);
321+ return 0;
322+}
323+#endif
324diff -Naur glibc-2.3.6.orig/stdlib/arc4randomII.c glibc-2.3.6/stdlib/arc4randomII.c
325--- glibc-2.3.6.orig/stdlib/arc4randomII.c 1970-01-01 00:00:00.000000000 +0000
326+++ glibc-2.3.6/stdlib/arc4randomII.c 2006-01-01 07:48:48.000000000 +0000
327@@ -0,0 +1,196 @@
328+/*
329+ * Arc4 random number generator for OpenBSD.
330+ * Copyright 1996 David Mazieres <dm@lcs.mit.edu>.
331+ *
332+ * Modification and redistribution in source and binary forms is
333+ * permitted provided that due credit is given to the author and the
334+ * OpenBSD project by leaving this copyright notice intact.
335+ */
336+
337+/*
338+ * This code is derived from section 17.1 of Applied Cryptography,
339+ * second edition, which describes a stream cipher allegedly
340+ * compatible with RSA Labs "RC4" cipher (the actual description of
341+ * which is a trade secret). The same algorithm is used as a stream
342+ * cipher called "arcfour" in Tatu Ylonen's ssh package.
343+ *
344+ * Here the stream cipher has been modified always to include the time
345+ * when initializing the state. That makes it impossible to
346+ * regenerate the same random sequence twice, so this can't be used
347+ * for encryption, but will generate good random numbers.
348+ *
349+ * RC4 is a registered trademark of RSA Laboratories.
350+ */
351+
352+/*
353+ * Modified by Robert Connolly from OpenBSD lib/libc/crypt/arc4random.c v1.11.
354+ * This is arc4randomII(3) using erandom.
355+ */
356+
357+#include <fcntl.h>
358+#include <stdlib.h>
359+#include <unistd.h>
360+#include <sys/types.h>
361+#include <sys/param.h>
362+#include <sys/time.h>
363+#include <sys/sysctl.h>
364+
365+#ifdef __GNUC__
366+#define inline __inline
367+#else /* !__GNUC__ */
368+#define inline
369+#endif /* !__GNUC__ */
370+
371+struct arc4_streamII {
372+ u_int8_t i;
373+ u_int8_t j;
374+ u_int8_t s[256];
375+};
376+
377+static int rs_initializedII;
378+static struct arc4_streamII rs;
379+static pid_t arc4_stir_pidII;
380+
381+static inline u_int8_t arc4_getbyteII(struct arc4_streamII *);
382+
383+static inline void
384+arc4_initII(struct arc4_streamII *as)
385+{
386+ int n;
387+
388+ for (n = 0; n < 256; n++)
389+ as->s[n] = n;
390+ as->i = 0;
391+ as->j = 0;
392+}
393+
394+static inline void
395+arc4_addrandomII(struct arc4_streamII *as, u_char *dat, int datlen)
396+{
397+ int n;
398+ u_int8_t si;
399+
400+ as->i--;
401+ for (n = 0; n < 256; n++) {
402+ as->i = (as->i + 1);
403+ si = as->s[as->i];
404+ as->j = (as->j + si + dat[n % datlen]);
405+ as->s[as->i] = as->s[as->j];
406+ as->s[as->j] = si;
407+ }
408+ as->j = as->i;
409+}
410+
411+static void
412+arc4_stirII(struct arc4_streamII *as)
413+{
414+ int n, fd;
415+ struct {
416+ struct timeval tv;
417+ u_int rnd[(128 - sizeof(struct timeval)) / sizeof(u_int)];
418+ } rdat;
419+
420+ gettimeofday(&rdat.tv, NULL);
421+
422+ /* /dev/urandom is a multithread interface, sysctl is not. */
423+ /* Try to use /dev/urandom before sysctl. */
424+ fd = open("/dev/erandom", O_RDONLY);
425+ if (fd != -1) {
426+ read(fd, rdat.rnd, sizeof(rdat.rnd));
427+ close(fd);
428+ }
429+
430+#if defined(SYSCTL_ERANDOM)
431+ else {
432+ /* /dev/urandom failed? Maybe we're in a chroot. */
433+ int mib[]={CTL_KERN, KERN_RANDOM, RANDOM_ERANDOM};
434+ u_int i;
435+ size_t len;
436+
437+ for (i = 0; i < sizeof(rdat.rnd) / sizeof(u_int); i++) {
438+ len = sizeof(u_int);
439+ if (sysctl(mib, 3, &rdat.rnd[i], &len, NULL, 0) == -1)
440+ break;
441+ }
442+ }
443+#endif
444+
445+ arc4_stir_pidII = getpid();
446+ /*
447+ * Time to give up. If no entropy could be found then we will just
448+ * use gettimeofday.
449+ */
450+ arc4_addrandomII(as, (void *)&rdat, sizeof(rdat));
451+
452+ /*
453+ * Discard early keystream, as per recommendations in:
454+ * http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps
455+ * We discard 256 words. A long word is 4 bytes.
456+ */
457+ for (n = 0; n < 256 * 4; n ++)
458+ arc4_getbyteII(as);
459+}
460+
461+static inline u_int8_t
462+arc4_getbyteII(struct arc4_streamII *as)
463+{
464+ u_int8_t si, sj;
465+
466+ as->i = (as->i + 1);
467+ si = as->s[as->i];
468+ as->j = (as->j + si);
469+ sj = as->s[as->j];
470+ as->s[as->i] = sj;
471+ as->s[as->j] = si;
472+ return (as->s[(si + sj) & 0xff]);
473+}
474+
475+static inline u_int32_t
476+arc4_getwordII(struct arc4_streamII *as)
477+{
478+ u_int32_t val;
479+ val = arc4_getbyteII(as) << 24;
480+ val |= arc4_getbyteII(as) << 16;
481+ val |= arc4_getbyteII(as) << 8;
482+ val |= arc4_getbyteII(as);
483+ return val;
484+}
485+
486+void
487+arc4random_stirII(void)
488+{
489+ if (!rs_initializedII) {
490+ arc4_initII(&rs);
491+ rs_initializedII = 1;
492+ }
493+ arc4_stirII(&rs);
494+}
495+
496+void
497+arc4random_addrandomII(u_char *dat, int datlen)
498+{
499+ if (!rs_initializedII)
500+ arc4random_stirII();
501+ arc4_addrandomII(&rs, dat, datlen);
502+}
503+
504+u_int32_t
505+arc4randomII(void)
506+{
507+ if (!rs_initializedII || arc4_stir_pidII != getpid())
508+ arc4random_stirII();
509+ return arc4_getwordII(&rs);
510+}
511+
512+#if 0
513+/*-------- Test code --------*/
514+#include <stdlib.h>
515+#include <stdio.h>
516+
517+int main(void) {
518+ int random_number;
519+ random_number = arc4randomII() % 65536;
520+ printf("A random number between 0 and 65536 is %d\n", random_number);
521+ return 0;
522+}
523+#endif
524diff -Naur glibc-2.3.6.orig/stdlib/stdlib.h glibc-2.3.6/stdlib/stdlib.h
525--- glibc-2.3.6.orig/stdlib/stdlib.h 2005-07-18 01:15:30.000000000 +0000
526+++ glibc-2.3.6/stdlib/stdlib.h 2006-01-01 07:48:48.000000000 +0000
527@@ -572,6 +572,15 @@
528 extern int lcong48_r (unsigned short int __param[7],
529 struct drand48_data *__buffer)
530 __THROW __nonnull ((1, 2));
531+
532+#define LIBC_HAS_ARC4RANDOM
533+u_int32_t arc4random(void);
534+void arc4random_stir(void);
535+void arc4random_addrandom(unsigned char *, int);
536+u_int32_t arc4randomII(void);
537+void arc4random_stirII(void);
538+void arc4random_addrandomII(unsigned char *, int);
539+
540 # endif /* Use misc. */
541 #endif /* Use SVID or X/Open. */