1 Submitted By: Robert Connolly <robert at linuxfromscratch dot org> (ashes)
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.
11 To get character devices do this:
12 mknod /dev/frandom c 235 11
13 mknod /dev/erandom c 235 12
15 Thanks to Eli Billauer
16 http://www.billauer.co.il/
17 http://frandom.sourceforge.net/
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/\
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.
32 +Fast random data generator suite (/dev/frandom and /dev/erandom)
34 + Fast random data/number generator support in kernel. This random
35 + generator is 10-50 times faster than /dev/urandom, and saves kernel
38 + If unsure, say Y unless you're tight on kernel size. This module is
39 + small and harmless otherwise.
41 + If you choose M, the sysctl interface will be disabled.
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
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
61 tristate ' Dual serial port support' CONFIG_DUALSP_SERIAL
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
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 \
76 + scx200.o fetchop.o frandom.o
78 mod-subdirs := joystick ftape drm drm-4.0 pcmcia
84 +obj-$(CONFIG_FRANDOM) += frandom.o
86 include $(TOPDIR)/Rules.make
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
95 +** Fast pseudo-random generator
97 +** (c) Copyright 2003 Eli Billauer
98 +** http://www.billauer.co.il
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.
105 +** Usage: mknod /dev/frandom c 235 11
106 +** mknod /dev/erandom c 235 12
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
117 +#include <linux/version.h>
118 +#include <linux/config.h>
119 +#include <linux/module.h>
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>
129 +#include <asm/uaccess.h>
131 +#if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,0))
132 +#include <linux/moduleparam.h>
135 +#define INTERNAL_SEED 0
136 +#define EXTERNAL_SEED 1
138 +#define FRANDOM_MAJOR 235
139 +#define FRANDOM_MINOR 11
140 +#define ERANDOM_MINOR 12
142 +static struct file_operations frandom_fops; /* Values assigned below */
144 +static int erandom_seeded = 0; /* Internal flag */
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 */
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");
166 +struct frandom_state
168 + struct semaphore sem; /* Semaphore on the state structure */
170 + u8 S[256]; /* The state array */
177 +static struct frandom_state *erandom_state;
179 +static inline void swap_byte(u8 *a, u8 *b)
188 +static void init_rand_state(struct frandom_state *state, int seedflag);
190 +void erandom_get_random_bytes(char *buf, size_t count)
192 + struct frandom_state *state = erandom_state;
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.
207 + if (down_interruptible(&state->sem)) {
208 + get_random_bytes(buf, count);
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
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");
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];
240 +static void init_rand_state(struct frandom_state *state, int seedflag)
242 + unsigned int i, j, k;
244 + u8 *seed = state->buf;
246 + if (seedflag == INTERNAL_SEED)
247 + erandom_get_random_bytes(seed, 256);
249 + get_random_bytes(seed, 256);
252 + for (i=0; i<256; i++)
258 + for (i=0; i<256; i++) {
259 + j = (j + S[i] + *seed++) & 0xff;
260 + swap_byte(&S[i], &S[j]);
263 + /* It's considered good practice to discard the first 256 bytes
264 + generated. So we do it:
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]);
274 + state->i = i; /* Save state */
278 +static int frandom_open(struct inode *inode, struct file *filp)
281 + struct frandom_state *state;
283 + int num =MINOR(inode->i_rdev);
284 + if ((num != frandom_minor) && (num != erandom_minor)) return -ENODEV;
286 + state = kmalloc(sizeof(struct frandom_state), GFP_KERNEL);
290 + state->buf = kmalloc(frandom_bufsize, GFP_KERNEL);
296 + sema_init(&state->sem, 1); /* Init semaphore as a mutex */
298 + if (num == frandom_minor)
299 + init_rand_state(state, EXTERNAL_SEED);
301 + init_rand_state(state, INTERNAL_SEED);
303 + filp->private_data = state;
305 +#if (LINUX_VERSION_CODE<KERNEL_VERSION(2,4,0))
309 + return 0; /* Success */
312 +static int frandom_release(struct inode *inode, struct file *filp)
315 + struct frandom_state *state = filp->private_data;
320 +#if (LINUX_VERSION_CODE<KERNEL_VERSION(2,4,0))
327 +static ssize_t frandom_read(struct file *filp, char *buf, size_t count,
330 + struct frandom_state *state = filp->private_data;
339 + if (down_interruptible(&state->sem))
340 + return -ERESTARTSYS;
342 + if ((frandom_chunklimit > 0) && (count > frandom_chunklimit))
343 + count = frandom_chunklimit;
345 + ret = count; /* It's either everything or an error... */
352 + if (count > frandom_bufsize)
353 + dobytes = frandom_bufsize;
357 + localbuf = state->buf;
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];
366 + if (copy_to_user(buf, state->buf, dobytes)) {
383 +static struct file_operations frandom_fops = {
384 + read: frandom_read,
385 + open: frandom_open,
386 + release: frandom_release,
389 +static void frandom_cleanup_module(void) {
390 + kfree(erandom_state->buf);
391 + kfree(erandom_state);
393 + unregister_chrdev(frandom_major, "frandom");
397 +static int frandom_init_module(void)
401 + /* The buffer size MUST be at least 256 bytes, because we assume that
402 + minimal length in init_rand_state().
404 + if (frandom_bufsize < 256) {
405 + printk(KERN_ERR "frandom: Refused to load because frandom_bufsize=%d < 256\n",frandom_bufsize);
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);
413 + erandom_state = kmalloc(sizeof(struct frandom_state), GFP_KERNEL);
414 + if (!erandom_state)
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);
425 + sema_init(&erandom_state->sem, 1); /* Init semaphore as a mutex */
427 + erandom_seeded = 0;
429 +#ifdef SET_MODULE_OWNER
430 + SET_MODULE_OWNER(&frandom_fops);
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()
437 + result = register_chrdev(frandom_major, "frandom", &frandom_fops);
439 + printk(KERN_WARNING "frandom: can't get major %d\n",frandom_major);
441 + kfree(erandom_state->buf);
442 + kfree(erandom_state);
446 + if (frandom_major == 0) frandom_major = result; /* dynamic */
448 + return 0; /* succeed */
451 +module_init(frandom_init_module);
452 +module_exit(frandom_cleanup_module);
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 @@
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: */
466 +void erandom_get_random_bytes(char *buf, size_t count);
468 +static int proc_do_erandom(ctl_table *table, int write, struct file *filp,
469 + void *buffer, size_t *lenp)
471 + ctl_table fake_table;
472 + unsigned char buf[64], random[16], *p;
475 + erandom_get_random_bytes(random, 16);
479 + for (i=0; i<16; i++) {
480 + sprintf(p, "%02x", random[i]);
484 + fake_table.data = buf;
485 + fake_table.maxlen = sizeof(buf);
487 + return proc_dostring(&fake_table, write, filp, buffer, lenp);
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)
495 + unsigned char random[16];
498 + if (!oldval || !oldlenp)
501 + erandom_get_random_bytes(random, 16);
503 + if (get_user(len, oldlenp))
508 + if (copy_to_user(oldval, random, len) ||
509 + put_user(len, oldlenp))
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},
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
537 /* /proc/sys/kernel/random */
538 +#define SYSCTL_ERANDOM
543 RANDOM_READ_THRESH=3,
544 RANDOM_WRITE_THRESH=4,
551 /* /proc/sys/bus/isa */