]> git.ipfire.org Git - ipfire-3.x.git/blob - glibc/patches/glibc-2.10.1-arc4random.patch
Move all packages to root.
[ipfire-3.x.git] / glibc / patches / glibc-2.10.1-arc4random.patch
1 Submitted By: Robert Connolly <robert at linuxfromscratch dot org> (ashes)
2 Date: 2006-01-01
3 Initial Package Version: 2.3.6
4 Upstream Status: Not submitted
5 Origin: http://www.openbsd.org/cgi-bin/cvsweb/src/lib/libc/crypt/arc4random.c
6 Description: This patch adds the arc4random() and arc4randomII() functions
7 to Glibc, and hooks so mktemp(3) can use arc4randomII().
8
9 Also see:
10 http://www.linuxfromscratch.org/hlfs/
11 http://www.linuxfromscratch.org/hints/downloads/files/entropy.txt
12
13 diff -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 +
91 diff -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 \
103 diff -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;
115 diff -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
324 diff -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
524 diff -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. */