]> git.ipfire.org Git - ipfire-2.x.git/blob - src/patches/linux-2.4.27-frandom-2.patch
git-svn-id: http://svn.ipfire.org/svn/ipfire/IPFire/source@16 ea5c0bd1-69bd-2848...
[ipfire-2.x.git] / src / patches / linux-2.4.27-frandom-2.patch
1 Submitted By: Robert Connolly <robert at linuxfromscratch dot org> (ashes)
2 Date: 2004-11-03
3 Initial Package Version: Linux 2.4.27
4 Upstream Status: Rejected Upstream
5 Origin: http://frandom.sourceforge.net/ - frandom-0.8
6 Description: This is usefull for smashing stack protector, wiping
7 discs, mktemp, arc4random, and more.
8 This source was modified for 2.4.26, and is enabled by default in
9 arch/i386/defconfig. A define was added to sysctl.h too.
10
11 To get character devices do this:
12 mknod /dev/frandom c 235 11
13 mknod /dev/erandom c 235 12
14
15 Thanks to Eli Billauer
16 http://www.billauer.co.il/
17 http://frandom.sourceforge.net/
18
19 Also see:
20 http://www.linuxfromscratch.org/hlfs/
21 http://www.linuxfromscratch.org/hints/downloads/files/entropy.txt
22 http://www.linuxfromscratch.org/~robert/hlfs/hints/attachments/entropy/\
23 frandom-0.8.tar.gz
24
25 diff -Naur linux-2.4.27.orig/Documentation/Configure.help linux-2.4.27.frandom/Documentation/Configure.help
26 --- linux-2.4.27.orig/Documentation/Configure.help 2004-08-07 23:26:04.000000000 +0000
27 +++ linux-2.4.27.frandom/Documentation/Configure.help 2004-11-04 01:11:24.126837840 +0000
28 @@ -18447,6 +18447,17 @@
29 input/output character sets. Say Y here for the UTF-8 encoding of
30 the Unicode/ISO9646 universal character set.
31
32 +Fast random data generator suite (/dev/frandom and /dev/erandom)
33 +CONFIG_FRANDOM
34 + Fast random data/number generator support in kernel. This random
35 + generator is 10-50 times faster than /dev/urandom, and saves kernel
36 + entropy.
37 +
38 + If unsure, say Y unless you're tight on kernel size. This module is
39 + small and harmless otherwise.
40 +
41 + If you choose M, the sysctl interface will be disabled.
42 +
43 Virtual terminal
44 CONFIG_VT
45 If you say Y here, you will get support for terminal devices with
46 diff -Naur linux-2.4.27.orig/arch/i386/defconfig linux-2.4.27.frandom/arch/i386/defconfig
47 --- linux-2.4.27.orig/arch/i386/defconfig 2004-08-07 23:26:04.000000000 +0000
48 +++ linux-2.4.27.frandom/arch/i386/defconfig 2004-11-04 01:11:24.150834192 +0000
49 @@ -579,6 +579,7 @@
50 #
51 CONFIG_VT=y
52 CONFIG_VT_CONSOLE=y
53 +CONFIG_FRANDOM=y
54 CONFIG_SERIAL=y
55 # CONFIG_SERIAL_CONSOLE is not set
56 # CONFIG_SERIAL_EXTENDED is not set
57 diff -Naur linux-2.4.27.orig/drivers/char/Config.in linux-2.4.27.frandom/drivers/char/Config.in
58 --- linux-2.4.27.orig/drivers/char/Config.in 2004-08-07 23:26:04.000000000 +0000
59 +++ linux-2.4.27.frandom/drivers/char/Config.in 2004-11-04 01:11:24.201826440 +0000
60 @@ -25,6 +25,7 @@
61 tristate ' Dual serial port support' CONFIG_DUALSP_SERIAL
62 fi
63 fi
64 +tristate 'Fast random data generator suite (/dev/frandom and /dev/erandom)' CONFIG_FRANDOM
65 dep_mbool 'Extended dumb serial driver options' CONFIG_SERIAL_EXTENDED $CONFIG_SERIAL
66 if [ "$CONFIG_SERIAL_EXTENDED" = "y" ]; then
67 bool ' Support more than 4 serial ports' CONFIG_SERIAL_MANY_PORTS
68 diff -Naur linux-2.4.27.orig/drivers/char/Makefile linux-2.4.27.frandom/drivers/char/Makefile
69 --- linux-2.4.27.orig/drivers/char/Makefile 2004-08-07 23:26:04.000000000 +0000
70 +++ linux-2.4.27.frandom/drivers/char/Makefile 2004-11-04 01:11:24.209825224 +0000
71 @@ -25,7 +25,7 @@
72 misc.o pty.o random.o selection.o serial.o \
73 sonypi.o tty_io.o tty_ioctl.o generic_serial.o \
74 au1000_gpio.o vac-serial.o hp_psaux.o nvram.o \
75 - scx200.o fetchop.o
76 + scx200.o fetchop.o frandom.o
77
78 mod-subdirs := joystick ftape drm drm-4.0 pcmcia
79
80 @@ -334,6 +334,8 @@
81 obj-y += ipmi/ipmi.o
82 endif
83
84 +obj-$(CONFIG_FRANDOM) += frandom.o
85 +
86 include $(TOPDIR)/Rules.make
87
88 fastdep:
89 diff -Naur linux-2.4.27.orig/drivers/char/frandom.c linux-2.4.27.frandom/drivers/char/frandom.c
90 --- linux-2.4.27.orig/drivers/char/frandom.c 1970-01-01 00:00:00.000000000 +0000
91 +++ linux-2.4.27.frandom/drivers/char/frandom.c 2004-11-04 01:11:24.213824616 +0000
92 @@ -0,0 +1,362 @@
93 +/*
94 +** frandom.c
95 +** Fast pseudo-random generator
96 +**
97 +** (c) Copyright 2003 Eli Billauer
98 +** http://www.billauer.co.il
99 +**
100 +** This program is free software; you can redistribute it and/or modify
101 +** it under the terms of the GNU General Public License as published by
102 +** the Free Software Foundation; either version 2 of the License, or
103 +** (at your option) any later version.
104 +**
105 +** Usage: mknod /dev/frandom c 235 11
106 +** mknod /dev/erandom c 235 12
107 +** insmod frandom
108 +**
109 +** This code is highly based upon the examples given in the book "Linux
110 +** Device Drivers" by Alessandro Rubini and Jonathan Corbet, published
111 +** by O'Reilly & Associates.
112 +** O'Reilly's release of this book on the web for free is highly
113 +** appreciated.
114 +**
115 +*/
116 +
117 +#include <linux/version.h>
118 +#include <linux/config.h>
119 +#include <linux/module.h>
120 +
121 +#include <linux/kernel.h>
122 +#include <linux/init.h>
123 +#include <linux/slab.h>
124 +#include <linux/fs.h>
125 +#include <linux/errno.h>
126 +#include <linux/types.h>
127 +#include <linux/random.h>
128 +
129 +#include <asm/uaccess.h>
130 +
131 +#if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,0))
132 +#include <linux/moduleparam.h>
133 +#endif
134 +
135 +#define INTERNAL_SEED 0
136 +#define EXTERNAL_SEED 1
137 +
138 +#define FRANDOM_MAJOR 235
139 +#define FRANDOM_MINOR 11
140 +#define ERANDOM_MINOR 12
141 +
142 +static struct file_operations frandom_fops; /* Values assigned below */
143 +
144 +static int erandom_seeded = 0; /* Internal flag */
145 +
146 +static int frandom_major = FRANDOM_MAJOR;
147 +static int frandom_minor = FRANDOM_MINOR;
148 +static int erandom_minor = ERANDOM_MINOR;
149 +static int frandom_bufsize = 256;
150 +static int frandom_chunklimit = 0; /* =0 means unlimited */
151 +
152 +MODULE_DESCRIPTION("Fast pseudo-random number generator");
153 +MODULE_LICENSE("GPL");
154 +MODULE_AUTHOR("Eli Billauer");
155 +MODULE_PARM(frandom_major,"i");
156 +MODULE_PARM_DESC(frandom_major,"Major number of /dev/frandom and /dev/erandom");
157 +MODULE_PARM(frandom_minor,"i");
158 +MODULE_PARM_DESC(frandom_minor,"Minor number of /dev/frandom");
159 +MODULE_PARM(erandom_minor,"i");
160 +MODULE_PARM_DESC(erandom_minor,"Minor number of /dev/erandom");
161 +MODULE_PARM(frandom_bufsize,"i");
162 +MODULE_PARM_DESC(frandom_bufsize,"Internal buffer size in bytes. Default is 256. Must be >= 256");
163 +MODULE_PARM(frandom_chunklimit,"i");
164 +MODULE_PARM_DESC(frandom_chunklimit,"Limit for read() blocks size. 0 (default) is unlimited, otherwise must be >= 256");
165 +
166 +struct frandom_state
167 +{
168 + struct semaphore sem; /* Semaphore on the state structure */
169 +
170 + u8 S[256]; /* The state array */
171 + u8 i;
172 + u8 j;
173 +
174 + char *buf;
175 +};
176 +
177 +static struct frandom_state *erandom_state;
178 +
179 +static inline void swap_byte(u8 *a, u8 *b)
180 +{
181 + u8 swapByte;
182 +
183 + swapByte = *a;
184 + *a = *b;
185 + *b = swapByte;
186 +}
187 +
188 +static void init_rand_state(struct frandom_state *state, int seedflag);
189 +
190 +void erandom_get_random_bytes(char *buf, size_t count)
191 +{
192 + struct frandom_state *state = erandom_state;
193 + int k;
194 +
195 + unsigned int i;
196 + unsigned int j;
197 + u8 *S;
198 +
199 + /* If we fail to get the semaphore, we revert to external random data.
200 + Since semaphore blocking is expected to be very rare, and interrupts
201 + during these rare and very short periods of time even less frequent,
202 + we take the better-safe-than-sorry approach, and fill the buffer
203 + some expensive random data, in case the caller wasn't aware of this
204 + possibility, and expects random data anyhow.
205 + */
206 +
207 + if (down_interruptible(&state->sem)) {
208 + get_random_bytes(buf, count);
209 + return;
210 + }
211 +
212 + /* We seed erandom as late as possible, hoping that the kernel's main
213 + RNG is already restored in the boot sequence (not critical, but
214 + better.
215 + */
216 +
217 + if (!erandom_seeded) {
218 + erandom_seeded = 1;
219 + init_rand_state(state, EXTERNAL_SEED);
220 + printk(KERN_INFO "frandom: Seeded global generator now (used by erandom)\n");
221 + }
222 +
223 + i = state->i;
224 + j = state->j;
225 + S = state->S;
226 +
227 + for (k=0; k<count; k++) {
228 + i = (i + 1) & 0xff;
229 + j = (j + S[i]) & 0xff;
230 + swap_byte(&S[i], &S[j]);
231 + *buf++ = S[(S[i] + S[j]) & 0xff];
232 + }
233 +
234 + state->i = i;
235 + state->j = j;
236 +
237 + up(&state->sem);
238 +}
239 +
240 +static void init_rand_state(struct frandom_state *state, int seedflag)
241 +{
242 + unsigned int i, j, k;
243 + u8 *S;
244 + u8 *seed = state->buf;
245 +
246 + if (seedflag == INTERNAL_SEED)
247 + erandom_get_random_bytes(seed, 256);
248 + else
249 + get_random_bytes(seed, 256);
250 +
251 + S = state->S;
252 + for (i=0; i<256; i++)
253 + *S++=i;
254 +
255 + j=0;
256 + S = state->S;
257 +
258 + for (i=0; i<256; i++) {
259 + j = (j + S[i] + *seed++) & 0xff;
260 + swap_byte(&S[i], &S[j]);
261 + }
262 +
263 + /* It's considered good practice to discard the first 256 bytes
264 + generated. So we do it:
265 + */
266 +
267 + i=0; j=0;
268 + for (k=0; k<256; k++) {
269 + i = (i + 1) & 0xff;
270 + j = (j + S[i]) & 0xff;
271 + swap_byte(&S[i], &S[j]);
272 + }
273 +
274 + state->i = i; /* Save state */
275 + state->j = j;
276 +}
277 +
278 +static int frandom_open(struct inode *inode, struct file *filp)
279 +{
280 +
281 + struct frandom_state *state;
282 +
283 + int num =MINOR(inode->i_rdev);
284 + if ((num != frandom_minor) && (num != erandom_minor)) return -ENODEV;
285 +
286 + state = kmalloc(sizeof(struct frandom_state), GFP_KERNEL);
287 + if (!state)
288 + return -ENOMEM;
289 +
290 + state->buf = kmalloc(frandom_bufsize, GFP_KERNEL);
291 + if (!state->buf) {
292 + kfree(state);
293 + return -ENOMEM;
294 + }
295 +
296 + sema_init(&state->sem, 1); /* Init semaphore as a mutex */
297 +
298 + if (num == frandom_minor)
299 + init_rand_state(state, EXTERNAL_SEED);
300 + else
301 + init_rand_state(state, INTERNAL_SEED);
302 +
303 + filp->private_data = state;
304 +
305 +#if (LINUX_VERSION_CODE<KERNEL_VERSION(2,4,0))
306 + MOD_INC_USE_COUNT;
307 +#endif
308 +
309 + return 0; /* Success */
310 +}
311 +
312 +static int frandom_release(struct inode *inode, struct file *filp)
313 +{
314 +
315 + struct frandom_state *state = filp->private_data;
316 +
317 + kfree(state->buf);
318 + kfree(state);
319 +
320 +#if (LINUX_VERSION_CODE<KERNEL_VERSION(2,4,0))
321 + MOD_DEC_USE_COUNT;
322 +#endif
323 +
324 + return 0;
325 +}
326 +
327 +static ssize_t frandom_read(struct file *filp, char *buf, size_t count,
328 + loff_t *f_pos)
329 +{
330 + struct frandom_state *state = filp->private_data;
331 + ssize_t ret;
332 + int dobytes, k;
333 + char *localbuf;
334 +
335 + unsigned int i;
336 + unsigned int j;
337 + u8 *S;
338 +
339 + if (down_interruptible(&state->sem))
340 + return -ERESTARTSYS;
341 +
342 + if ((frandom_chunklimit > 0) && (count > frandom_chunklimit))
343 + count = frandom_chunklimit;
344 +
345 + ret = count; /* It's either everything or an error... */
346 +
347 + i = state->i;
348 + j = state->j;
349 + S = state->S;
350 +
351 + while (count) {
352 + if (count > frandom_bufsize)
353 + dobytes = frandom_bufsize;
354 + else
355 + dobytes = count;
356 +
357 + localbuf = state->buf;
358 +
359 + for (k=0; k<dobytes; k++) {
360 + i = (i + 1) & 0xff;
361 + j = (j + S[i]) & 0xff;
362 + swap_byte(&S[i], &S[j]);
363 + *localbuf++ = S[(S[i] + S[j]) & 0xff];
364 + }
365 +
366 + if (copy_to_user(buf, state->buf, dobytes)) {
367 + ret = -EFAULT;
368 + goto out;
369 + }
370 +
371 + buf += dobytes;
372 + count -= dobytes;
373 + }
374 +
375 + out:
376 + state->i = i;
377 + state->j = j;
378 +
379 + up(&state->sem);
380 + return ret;
381 +}
382 +
383 +static struct file_operations frandom_fops = {
384 + read: frandom_read,
385 + open: frandom_open,
386 + release: frandom_release,
387 +};
388 +
389 +static void frandom_cleanup_module(void) {
390 + kfree(erandom_state->buf);
391 + kfree(erandom_state);
392 +
393 + unregister_chrdev(frandom_major, "frandom");
394 +}
395 +
396 +
397 +static int frandom_init_module(void)
398 +{
399 + int result;
400 +
401 + /* The buffer size MUST be at least 256 bytes, because we assume that
402 + minimal length in init_rand_state().
403 + */
404 + if (frandom_bufsize < 256) {
405 + printk(KERN_ERR "frandom: Refused to load because frandom_bufsize=%d < 256\n",frandom_bufsize);
406 + return -EINVAL;
407 + }
408 + if ((frandom_chunklimit != 0) && (frandom_chunklimit < 256)) {
409 + printk(KERN_ERR "frandom: Refused to load because frandom_chunklimit=%d < 256 and != 0\n",frandom_chunklimit);
410 + return -EINVAL;
411 + }
412 +
413 + erandom_state = kmalloc(sizeof(struct frandom_state), GFP_KERNEL);
414 + if (!erandom_state)
415 + return -ENOMEM;
416 +
417 + /* This specific buffer is only used for seeding, so we need
418 + 256 bytes exactly */
419 + erandom_state->buf = kmalloc(256, GFP_KERNEL);
420 + if (!erandom_state->buf) {
421 + kfree(erandom_state);
422 + return -ENOMEM;
423 + }
424 +
425 + sema_init(&erandom_state->sem, 1); /* Init semaphore as a mutex */
426 +
427 + erandom_seeded = 0;
428 +
429 +#ifdef SET_MODULE_OWNER
430 + SET_MODULE_OWNER(&frandom_fops);
431 +#endif
432 + /*
433 + * Register your major, and accept a dynamic number. This is the
434 + * first thing to do, in order to avoid releasing other module's
435 + * fops in frandom_cleanup_module()
436 + */
437 + result = register_chrdev(frandom_major, "frandom", &frandom_fops);
438 + if (result < 0) {
439 + printk(KERN_WARNING "frandom: can't get major %d\n",frandom_major);
440 +
441 + kfree(erandom_state->buf);
442 + kfree(erandom_state);
443 +
444 + return result;
445 + }
446 + if (frandom_major == 0) frandom_major = result; /* dynamic */
447 +
448 + return 0; /* succeed */
449 +}
450 +
451 +module_init(frandom_init_module);
452 +module_exit(frandom_cleanup_module);
453 +
454 +EXPORT_SYMBOL(erandom_get_random_bytes);
455 diff -Naur linux-2.4.27.orig/drivers/char/random.c linux-2.4.27.frandom/drivers/char/random.c
456 --- linux-2.4.27.orig/drivers/char/random.c 2004-02-18 13:36:31.000000000 +0000
457 +++ linux-2.4.27.frandom/drivers/char/random.c 2004-11-04 01:11:24.260817472 +0000
458 @@ -1870,6 +1870,60 @@
459 return 1;
460 }
461
462 +#ifdef CONFIG_FRANDOM
463 +/* We don't really want to create a header file for frandom
464 + at this stage, so here's the prototype: */
465 +
466 +void erandom_get_random_bytes(char *buf, size_t count);
467 +
468 +static int proc_do_erandom(ctl_table *table, int write, struct file *filp,
469 + void *buffer, size_t *lenp)
470 +{
471 + ctl_table fake_table;
472 + unsigned char buf[64], random[16], *p;
473 + int i;
474 +
475 + erandom_get_random_bytes(random, 16);
476 +
477 + p=buf;
478 +
479 + for (i=0; i<16; i++) {
480 + sprintf(p, "%02x", random[i]);
481 + p+=2;
482 + }
483 +
484 + fake_table.data = buf;
485 + fake_table.maxlen = sizeof(buf);
486 +
487 + return proc_dostring(&fake_table, write, filp, buffer, lenp);
488 +}
489 +
490 +
491 +static int erandom_strategy(ctl_table *table, int *name, int nlen,
492 + void *oldval, size_t *oldlenp,
493 + void *newval, size_t newlen, void **context)
494 +{
495 + unsigned char random[16];
496 + unsigned int len;
497 +
498 + if (!oldval || !oldlenp)
499 + return 1;
500 +
501 + erandom_get_random_bytes(random, 16);
502 +
503 + if (get_user(len, oldlenp))
504 + return -EFAULT;
505 + if (len) {
506 + if (len > 16)
507 + len = 16;
508 + if (copy_to_user(oldval, random, len) ||
509 + put_user(len, oldlenp))
510 + return -EFAULT;
511 + }
512 + return 1;
513 +}
514 +#endif
515 +
516 ctl_table random_table[] = {
517 {RANDOM_POOLSIZE, "poolsize",
518 &sysctl_poolsize, sizeof(int), 0644, NULL,
519 @@ -1888,6 +1942,11 @@
520 {RANDOM_BOOT_ID, "boot_id",
521 &sysctl_bootid, 16, 0444, NULL,
522 &proc_do_uuid, &uuid_strategy},
523 +#ifdef CONFIG_FRANDOM
524 + {RANDOM_ERANDOM, "erandom",
525 + NULL, 16, 0444, NULL,
526 + &proc_do_erandom, &erandom_strategy},
527 +#endif
528 {RANDOM_UUID, "uuid",
529 NULL, 16, 0444, NULL,
530 &proc_do_uuid, &uuid_strategy},
531 diff -Naur linux-2.4.27.orig/include/linux/sysctl.h linux-2.4.27.frandom/include/linux/sysctl.h
532 --- linux-2.4.27.orig/include/linux/sysctl.h 2004-08-07 23:26:06.000000000 +0000
533 +++ linux-2.4.27.frandom/include/linux/sysctl.h 2004-11-04 01:13:02.000000000 +0000
534 @@ -184,6 +184,7 @@
535 };
536
537 /* /proc/sys/kernel/random */
538 +#define SYSCTL_ERANDOM
539 enum
540 {
541 RANDOM_POOLSIZE=1,
542 @@ -191,7 +192,8 @@
543 RANDOM_READ_THRESH=3,
544 RANDOM_WRITE_THRESH=4,
545 RANDOM_BOOT_ID=5,
546 - RANDOM_UUID=6
547 + RANDOM_UUID=6,
548 + RANDOM_ERANDOM=7
549 };
550
551 /* /proc/sys/bus/isa */