? INSTALL ? Makefile.in ? aclocal.m4 ? autom4te.cache ? build ? build-aux ? config.h.in ? configure ? entropy_patch.diff ? device/entropy.c ? device/entropy.h ? doc/mach.info ? doc/mach.info-1 ? doc/mach.info-2 ? doc/stamp-vti ? doc/version.texi Index: Makefrag.am =================================================================== RCS file: /sources/hurd/gnumach/Attic/Makefrag.am,v retrieving revision 1.1.2.12 diff -u -r1.1.2.12 Makefrag.am --- Makefrag.am 2 Jun 2007 13:23:21 -0000 1.1.2.12 +++ Makefrag.am 9 Aug 2007 02:11:39 -0000 @@ -292,6 +292,14 @@ device/kmsg.h endif +# +# kernel entrophy generator device + +if enable_entropy +libkernel_a_SOURCES += \ + device/entropy.c + device/entropy.h +endif # # Version number. Index: configfrag.ac =================================================================== RCS file: /sources/hurd/gnumach/Attic/configfrag.ac,v retrieving revision 1.1.2.7 diff -u -r1.1.2.7 configfrag.ac --- configfrag.ac 4 Aug 2007 18:50:19 -0000 1.1.2.7 +++ configfrag.ac 9 Aug 2007 02:11:39 -0000 @@ -128,7 +128,18 @@ [else] AM_CONDITIONAL([enable_kmsg], [false]) [fi] - + + +AC_ARG_ENABLE([entropy], + AS_HELP_STRING([--disable-entropy], [disable use of entropy device])) +[if [ x"$enable_entropy" != xno ]; then] + AC_DEFINE([MACH_ENTROPY], [], [enable use of entropy device]) + AM_CONDITIONAL([enable_entropy], [true]) +[else] + AM_CONDITIONAL([enable_entropy], [false]) +[fi] + + # # Set up `SYSTYPE/SYSTYPE' and `SYSTYPE/include/mach/SYSTYPE' links. # @@ -138,7 +149,7 @@ # . AC_CONFIG_LINKS([machine:$systype/$systype mach/machine:$systype/include/mach/$systype]) - + dnl Local Variables: dnl mode: autoconf dnl End: Index: device/blkio.c =================================================================== RCS file: /sources/hurd/gnumach/device/Attic/blkio.c,v retrieving revision 1.1.1.1 diff -u -r1.1.1.1 blkio.c --- device/blkio.c 25 Feb 1997 21:28:13 -0000 1.1.1.1 +++ device/blkio.c 9 Aug 2007 02:11:40 -0000 @@ -36,7 +36,9 @@ #include #include - +#ifdef MACH_ENTROPY +#include +#endif io_return_t block_io(strat, max_count, ior) void (*strat)(); @@ -149,6 +151,10 @@ do { prev = next; next = prev->io_next; +#ifdef MACH_ENTROPY + /* Let's grab the cylinder numbers for entropy. */ + entropy_putdata (prev, sizeof(io_req_t), ENTROPY_HIGH_QUALITY); +#endif } while (next != 0 && prev->io_cylinder == next->io_cylinder); if (next == 0) { Index: device/cons.c =================================================================== RCS file: /sources/hurd/gnumach/device/Attic/cons.c,v retrieving revision 1.2.4.6 diff -u -r1.2.4.6 cons.c --- device/cons.c 13 Nov 2006 21:30:36 -0000 1.2.4.6 +++ device/cons.c 9 Aug 2007 02:11:40 -0000 @@ -44,6 +44,10 @@ #include #endif +#ifdef MACH_ENTROPY +#include +#endif + static int cn_inited = 0; static struct consdev *cn_tab = 0; /* physical console device info */ #ifndef MACH_KERNEL @@ -230,9 +234,19 @@ cngetc() { if (cn_tab) - return ((*cn_tab->cn_getc)(cn_tab->cn_dev, 1)); - if (romgetc) - return ((*romgetc)(1)); + { +#if defined(MACH_KERNEL) && defined(MACH_ENTROPY) + entropy_putchar (cn_tab->cn_dev, ENTROPY_MEDIUM_QUALITY); +#endif /* MACH_ENTROPY and MACH_ENTROPY */ + return ((*cn_tab->cn_getc)(cn_tab->cn_dev, 1)); + } + if (romgetc) + { +#if defined (MACH_KERNEL) && defined(MACH_ENTROPY) + entropy_putchar(*romgetc, ENTROPY_MEDIUM_QUALITY); +#endif /* MACH_KERNEL && MACH_ENTROPY */ + return ((*romgetc)(1)); + } return (0); } Index: i386/i386at/conf.c =================================================================== RCS file: /sources/hurd/gnumach/i386/i386at/Attic/conf.c,v retrieving revision 1.4.2.15 diff -u -r1.4.2.15 conf.c --- i386/i386at/conf.c 1 Apr 2007 22:10:40 -0000 1.4.2.15 +++ i386/i386at/conf.c 9 Aug 2007 02:11:40 -0000 @@ -61,6 +61,11 @@ extern int kmsgopen(), kmsgclose(), kmsgread(), kmsggetstat(); #define kmsgname "kmsg" +#ifdef MACH_ENTROPY +#define entropyname "entropy" +extern int entropyopen(), entropyclose(), entropyread(), entropygetstat(); +#endif + /* * List of devices - console must be at slot 0 */ @@ -120,6 +125,12 @@ nodev }, #endif +#ifdef MACH_ENTROPY + { entropyname, entropyopen, entropyclose, entropyread, + nodev, entropygetstat, nodev, nomap, + nodev, nulldev, nulldev, 0, + nodev }, +#endif }; int dev_name_count = sizeof(dev_name_list)/sizeof(dev_name_list[0]); Index: i386/i386at/kd.c =================================================================== RCS file: /sources/hurd/gnumach/i386/i386at/Attic/kd.c,v retrieving revision 1.5.2.13 diff -u -r1.5.2.13 kd.c --- i386/i386at/kd.c 7 May 2007 22:04:53 -0000 1.5.2.13 +++ i386/i386at/kd.c 9 Aug 2007 02:11:41 -0000 @@ -85,6 +85,11 @@ #include #include /* for struct uio (!) */ #include + +#if defined (MACH_KERNEL) && defined(MACH_ENTROPY) +#include +#endif /* MACH_KERNEL and MACH _ENTROPY */ + #include #include #include @@ -811,6 +816,16 @@ up = TRUE; scancode &= ~K_UP; } + +#ifdef MACH_KERNEL +#ifdef MACH_ENTROPY + /* Sune Kirkeby's entropy patch (which was a port of the + linux entropy drivers for GNU mach) placed the keyboard + entropy source here. I looked at that for an idea of where + how to do write this driver. */ + entropy_putchar(scancode | (up ? 0200 : 0), ENTROPY_LOW_QUALITY); +#endif /* MACH_ENTROPY */ +#endif /* MACH_KERNEL */ if (scancode < NUMKEYS) { /* Lookup in map, then process. */ char_idx = kdstate2idx(kd_state, kd_extended); Index: i386/i386at/kd_mouse.c =================================================================== RCS file: /sources/hurd/gnumach/i386/i386at/Attic/kd_mouse.c,v retrieving revision 1.3.2.8 diff -u -r1.3.2.8 kd_mouse.c --- i386/i386at/kd_mouse.c 13 Nov 2006 21:30:36 -0000 1.3.2.8 +++ i386/i386at/kd_mouse.c 9 Aug 2007 02:11:41 -0000 @@ -70,6 +70,9 @@ #ifdef MACH_KERNEL #include #include +#ifdef MACH_ENTROPY +#include +#endif /* MACH_ENTROPY */ #else /* MACH_KERNEL */ #include #include @@ -677,6 +680,11 @@ moved.mm_deltaX = (char)mousebuf[1] + (char)mousebuf[3]; moved.mm_deltaY = (char)mousebuf[2] + (char)mousebuf[4]; +#ifdef MACH_ENTROPY + /* Kick some mouse data to the entropy driver. */ + entropy_putchar((buttonchanges + moved.mm_deltaX + + moved.mm_deltaY), ENTROPY_HIGH_QUALITY); +#endif if (moved.mm_deltaX != 0 || moved.mm_deltaY != 0) mouse_moved(moved); Index: linux/configfrag.ac =================================================================== RCS file: /sources/hurd/gnumach/linux/Attic/configfrag.ac,v retrieving revision 1.1.2.6 diff -u -r1.1.2.6 configfrag.ac --- linux/configfrag.ac 4 Aug 2007 18:50:19 -0000 1.1.2.6 +++ linux/configfrag.ac 9 Aug 2007 02:11:42 -0000 @@ -604,6 +604,15 @@ linux/dev/include/asm:linux/dev/include/asm-$systype]) [else] AM_CONDITIONAL([CODE_linux], [false]) [fi] + +AC_ARG_ENABLE([entropy], + AS_HELP_STRING([--disable-entropy], [disable use of entropy device])) + [if [ x"$enable_entropy" != xno ]; then] + AC_DEFINE([MACH_ENTROPY], [], [enable use of entropy device]) + AM_CONDITIONAL([enable_entropy], [true]) + [else] + AM_CONDITIONAL([enable_entropy], [false]) +[fi] dnl Local Variables: dnl mode: autoconf Index: linux/dev/glue/misc.c =================================================================== RCS file: /sources/hurd/gnumach/linux/dev/glue/Attic/misc.c,v retrieving revision 1.2 diff -u -r1.2 misc.c --- linux/dev/glue/misc.c 18 Sep 2001 21:14:19 -0000 1.2 +++ linux/dev/glue/misc.c 9 Aug 2007 02:11:42 -0000 @@ -67,6 +67,10 @@ #include #include +#ifdef MACH_ENTROPY +#include +#endif + extern boolean_t vm_map_lookup_entry (register vm_map_t, register vm_offset_t, vm_map_entry_t *); extern int printf (const char *, ...); @@ -224,6 +228,15 @@ void add_blkdev_randomness (int major) { +#ifdef MACH_ENTROPY + /* This is useless for good quality, so we'll only use if it nothing + else is available - The problem is that mach only has 1 block + device, floppy (major 3 corresponds to Ctrl C) so this is useless + for entropic sources. If we ever get more block devices the + quality should be upped for additional entropy. */ + + entropy_putchar(major, ENTROPY_POOR_QUALITY); +#endif } void Index: linux/dev/glue/net.c =================================================================== RCS file: /sources/hurd/gnumach/linux/dev/glue/Attic/net.c,v retrieving revision 1.1.4.7 diff -u -r1.1.4.7 net.c --- linux/dev/glue/net.c 27 Mar 2007 22:47:11 -0000 1.1.4.7 +++ linux/dev/glue/net.c 9 Aug 2007 02:11:42 -0000 @@ -97,6 +97,11 @@ #include #include +#ifdef MACH_KERNEL +#ifdef MACH_ENTROPY +#include +#endif /* MACH_KERNEL */ +#endif /* MACH_ENTROPY */ extern int linux_intr_pri; /* One of these is associated with each instance of a device. */ @@ -299,6 +304,11 @@ ph->length = (skb->len - sizeof (struct ether_header) + sizeof (struct packet_header)); +#ifdef MACH_ENTROPY + /* Grab the packet for entropy purposes. */ + entropy_putdata(ph + 1, skb->len - sizeof(struct ether_header), ENTROPY_HIGH_QUALITY); +#endif + dev_kfree_skb (skb, FREE_READ); net_kmsg(kmsg)->sent = FALSE; /* Mark packet as received. */ Index: linux/dev/include/linux/blk.h =================================================================== RCS file: /sources/hurd/gnumach/linux/dev/include/linux/Attic/blk.h,v retrieving revision 1.2 diff -u -r1.2 blk.h --- linux/dev/include/linux/blk.h 5 Apr 2001 06:39:21 -0000 1.2 +++ linux/dev/include/linux/blk.h 9 Aug 2007 02:11:43 -0000 @@ -90,7 +90,7 @@ #endif /* CONFIG_BLK_DEV_MD */ extern void set_device_ro(kdev_t dev,int flag); -void add_blkdev_randomness(int major); +extern void add_blkdev_randomness(int major); extern int floppy_init(void); extern void rd_load(void); @@ -136,7 +136,10 @@ #define DEVICE_NR(device) (MINOR(device)) #define DEVICE_ON(device) #define DEVICE_OFF(device) + +#ifndef MACH_ENTROPY #define DEVICE_NO_RANDOM +#endif #elif (MAJOR_NR == FLOPPY_MAJOR) --- /dev/null 2007-04-05 09:18:41.000066712 -0400 +++ device/entropy.c 2007-08-08 17:54:38.000000001 -0400 @@ -0,0 +1,448 @@ +/* + * Mach Kernel - Entropy Generating Device + * Copyright (C) 2007 Free Software Foundation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* System Header Files */ +#include +#include + +/* Local Header Files */ +#include "entropy.h" + +/* Variable Declarations */ + +/* Entropy Buffer */ +static char entropy_buffer[ENTROPYBUFSIZE]; + +/* Lock to each function */ +decl_simple_lock_data(static,entropy_lock); + +/* Current read offset */ +static int entropy_read_offset = 0; + +/* Current write offset */ +static int entropy_write_offset = 0; + +/* If this device is already initalized */ +static int entropy_init_done = 0; + +/* I/O queue requests for blocking read */ +static queue_head_t entropy_read_queue; + +/* Generate/Use Entropic Average Quality */ +static int use_entropic_average = 0; + +/* Entropic Quality */ +static int entropy_qualities[ENTROPYBUFSIZE]; + +/* Current Entropic Quality (scale of 0-10) */ +static float entropy_average = 0.00; + +/* + * The following is from linux's random.c, and is used + * under the GPL. + * + * Look there for a full explination on what these numbers + * mean and how this works. + */ + +static struct poolinfo { + int poolwords; + int tap1, tap2, tap3, tap4, tap5; + } poolinfo_table [] = { + /* x^128 + x^103 + x^76 + x^51 +x^25 + x + 1 -- 105 */ + { 128, 103, 76, 51, 25, 1 }, + /* x^32 + x^26 + x^20 + x^14 + x^7 + x + 1 -- 15 */ + { 32, 26, 20, 14, 7, 1 }, + /* x^2048 + x^1638 + x^1231 + x^819 + x^411 + x + 1 -- 115 */ + { 2048, 1638, 1231, 819, 411, 1 }, + /* x^1024 + x^817 + x^615 + x^412 + x^204 + x + 1 -- 290 */ + { 1024, 817, 615, 412, 204, 1 }, + /* x^1024 + x^819 + x^616 + x^410 + x^207 + x^2 + 1 -- 115 */ + { 1024, 819, 616, 410, 207, 2 }, + /* x^512 + x^411 + x^308 + x^208 + x^104 + x + 1 -- 225 */ + { 512, 411, 308, 208, 104, 1 }, + /* x^512 + x^409 + x^307 + x^206 + x^102 + x^2 + 1 -- 95 */ + { 512, 409, 307, 206, 102, 2 }, + /* x^512 + x^409 + x^309 + x^205 + x^103 + x^2 + 1 -- 95 */ + { 512, 409, 309, 205, 103, 2 }, + /* x^256 + x^205 + x^155 + x^101 + x^52 + x + 1 -- 125 */ + { 256, 205, 155, 101, 52, 1 }, + /* x^128 + x^103 + x^78 + x^51 + x^27 + x^2 + 1 -- 70 */ + { 128, 103, 78, 51, 27, 2 }, + /* x^64 + x^52 + x^39 + x^26 + x^14 + x + 1 -- 15 */ + { 64, 52, 39, 26, 14, 1 }, +}; + +/* Number of taps -1 */ +const int number_of_taps = 10; + +void +entropyinit() +{ + /* Sanity check! */ + if (entropy_init_done == 1) { + assert(entropy_init_done); + } + + /* Setup locks */ + queue_init(&entropy_read_queue); + simple_lock_init(&entropy_lock); + entropy_init_done = 1; +} + +io_return_t +entropyopen(dev_t dev, int flag, io_req_t ior) +{ + /* Check to see if we've initalized entropy. */ + if (entropy_init_done == 0) + { + entropyinit(); + } + + /* Lock the function so we don't get a race condition. */ + simple_lock(&entropy_lock); + + /* We're done, unlock, and return success. */ + simple_unlock(&entropy_lock); + return D_SUCCESS; +} + +io_return_t +entropyclose(dev_t dev, int flag) +{ + return D_SUCCESS; +} + +/* Forward Declaration */ +static boolean_t entropy_read_done(io_req_t ior); + +io_return_t +entropyread(dev_t dev, io_req_t ior) +{ + /* Possible error code. */ + int err; + + /* Amount of entropy we want to read out. */ + int amt; + + /* Amount of entropy we have to read out. */ + int len; + + /* Allocate memory. */ + err = device_read_alloc(ior, ior->io_count); + if (err != KERN_SUCCESS) + { + return err; + } + + /* Lock the device. */ + simple_lock(&entropy_lock); + if (entropy_read_offset == entropy_write_offset) + { + + /* We got no entropy at the moment, queue it up. */ + if (ior->io_mode & D_NOWAIT) { + /* Got a non-blocking socket, so just tell it we would + block. */ + simple_unlock(&entropy_lock); + return D_WOULD_BLOCK; + } + + /* Pass the point to the read_done function which will notify if + the IO read is REALLY done. */ + + ior->io_done = entropy_read_done; + + /* queue it up. */ + enqueue_tail(&entropy_read_queue, (queue_entry_t) ior); + simple_unlock(&entropy_lock); + return D_IO_QUEUED; + } + + /* Determine how much we're reading out. */ + len = entropy_write_offset - entropy_read_offset; + + if (len < 0 ) + len += ENTROPYBUFSIZE; + + amt = ior->io_count; + if (amt > len) + amt = len; + if (entropy_read_offset + amt <= ENTROPYBUFSIZE) + { + /* Copy available entropy into the device buffer. */ + memcpy (ior->io_data, entropy_buffer + entropy_read_offset, amt); + } else { + /* We need to wrap around so do it in two copies. */ + int cnt; + cnt = ENTROPYBUFSIZE - entropy_read_offset; + memcpy(ior->io_data, entropy_buffer + entropy_read_offset, cnt); + memcpy(ior->io_data, entropy_buffer, amt - cnt); + } + + /* Move the read offset. */ + entropy_read_offset += amt; + if (entropy_read_offset >= ENTROPYBUFSIZE) { + entropy_read_offset -= ENTROPYBUFSIZE; + } + + /* Notify the caller how much data we were able to return. */ + ior->io_residual = ior->io_count - amt; + + /* Since the buffer is no longer full, stop generating averages + until its refilled */ + use_entropic_average = 0; + + /* Unlock, and return success. */ + simple_unlock(&entropy_lock); + return D_SUCCESS; +} + +/* This function called when the io read is complete by + device_read. */ +static boolean_t +entropy_read_done(io_req_t ior) +{ + /* Amount of entropy we want. */ + int amt; + + /* Amount of entropy we have. */ + int len; + + /* Lock the device. */ + simple_lock(&entropy_lock); + if (entropy_read_offset == entropy_write_offset) + { + /* The queue is empty so return false. */ + ior->io_done = entropy_read_done; + enqueue_tail(&entropy_read_queue, (queue_entry_t) ior); + simple_unlock (&entropy_lock); + return FALSE; + } + + len = entropy_write_offset - entropy_read_offset; + if (len < 0) + len += ENTROPYBUFSIZE; + + amt = ior->io_count; + if (amt > len) + amt = len; + + if (entropy_read_offset + amt <= ENTROPYBUFSIZE) + { + /* Copy the data from the buffer. */ + memcpy (ior->io_data, entropy_buffer + entropy_read_offset, amt); + } + else + { + /* The buffer needs to wrap around, so copy in two + installments. */ + int cnt; + + cnt = ENTROPYBUFSIZE - entropy_read_offset; + memcpy (ior->io_data, entropy_buffer + entropy_read_offset, cnt); + memcpy (ior->io_data + cnt, entropy_buffer, amt - cnt); + } + + + entropy_read_offset += amt; + if (entropy_read_offset >= ENTROPYBUFSIZE) + { + entropy_read_offset -= ENTROPYBUFSIZE; + } + + ior->io_residual = ior->io_count - amt; + + /* The entropy buffer is no longer full, stop generating averages */ + use_entropic_average = 0; + + /* Finish up, and unlock */ + simple_unlock(&entropy_lock); + ds_read_done (ior); + + return TRUE; +} + +io_return_t +entropygetstat(dev_t dev, int flavor, int *data, unsigned int *count) +{ + switch (flavor) + { + case DEV_GET_SIZE: + data[DEV_GET_SIZE_DEVICE_SIZE] = 0; + data[DEV_GET_SIZE_RECORD_SIZE] = 1; + *count = DEV_GET_SIZE_COUNT; + break; + default: + return D_INVALID_OPERATION; + } + + return D_SUCCESS; +} + +void +entropy_putchar(int c, enum entropy_quality quality) +{ + /* We'll get data from a given source, and stick it in the + buffer. */ + io_req_t ior; + + /* Twist table, and twisting and mixing code adopted from Linux's + random.c. */ + + static unsigned long const twist_table [8] = { + 0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158, + 0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 }; + /* Taps available for use. */ + unsigned long int tap1, tap2, tap3, tap4, tap5; + + /* Random mask to twist by. */ + int wordmask; + + /* Bit rotation of the taps. */ + static int input_rotate; + + /* Current Tap in use. */ + static short current_tap; + + /* Input being twisted. */ + unsigned long word; + + /* Its possible we MIGHT get here before the device is opened so + just make sure we're initalized before doing anything! */ + + if(!entropy_init_done) + entropyinit(); + + /* See if we're currently calculating averages. If so, will the + incoming entropy improve the average? */ + if (use_entropic_average == 1) + if (entropy_average > quality) + /* Entropy isn't good enough, not using it */ + return; + + /* Ok, we're going to TRY to lock since we don't want to block trying + to get the lock. */ + + if (!simple_lock_try(&entropy_lock)) + /* Didn't get it, bail out. */ + return; + + /* Get the taps based on which array to use. */ + wordmask = poolinfo_table[current_tap].poolwords - 1; + tap1 = poolinfo_table[current_tap].tap1; + tap2 = poolinfo_table[current_tap].tap2; + tap3 = poolinfo_table[current_tap].tap3; + tap4 = poolinfo_table[current_tap].tap4; + tap5 = poolinfo_table[current_tap].tap5; + + /* Mix the tap into the incoming entropy. */ + c++; + word = ((c << input_rotate) | (c >> (32 - input_rotate))); + + /* XOR in the various taps, then add to the buffer. */ + word ^= entropy_buffer[(entropy_write_offset + tap1) & wordmask]; + word ^= entropy_buffer[(entropy_write_offset + tap2) & wordmask]; + word ^= entropy_buffer[(entropy_write_offset + tap3) & wordmask]; + word ^= entropy_buffer[(entropy_write_offset + tap4) & wordmask]; + word ^= entropy_buffer[(entropy_write_offset + tap5) & wordmask]; + + /* Add the entropy and its quality to the buffer. */ + entropy_buffer[entropy_write_offset] = (word >> 3) ^ twist_table[word & 7]; + entropy_qualities[entropy_write_offset] = quality; + + /* Advance the pointer for the next write. */ + entropy_write_offset += 1; + + if (entropy_write_offset == ENTROPYBUFSIZE) + entropy_write_offset = 0; + + /* If the buffer been filled, start generating averages */ + if (entropy_write_offset+1 == entropy_read_offset) + use_entropic_average = 1; + + /* Lets generate the averages */ + if (use_entropic_average == 1 ) + { + int total = 0; + int i = 0; + + for (i = 0; i > ENTROPYBUFSIZE; i++) + total += entropy_qualities[i]; + + /* And now that we have the total, get the average */ + entropy_average = (float) total/ENTROPYBUFSIZE; + } + + /* Deep magic (tells any read functions more entropy is + available) */ + while ((ior = (io_req_t) dequeue_head (&entropy_read_queue)) != NULL) + iodone (ior); + + simple_unlock(&entropy_lock); +} + +/* This function is used to copy data from memory pointers directly + into the bufffer */ + +void +entropy_putdata (void *data, int size, enum entropy_quality quality) +{ + /* Used to tell reads that we got entropy. */ + io_req_t ior; + int i; + + /* See if we are initalized; if not, initalize the driver. */ + if (!entropy_init_done) + entropyinit(); + + /* See if we're currently calculating averages. If so, will the + incoming entropy improve the average? */ + if (use_entropic_average == 1) + if (entropy_average > quality) + /* Entropy isn't good enough, not using it */ + return; + + /* Try to grab a lock on the device, otherwise bail. */ + if (!simple_lock_try(&entropy_lock)) + return; + + /* Is the data we're copying in bigger then our buffer? */ + if (size >= ENTROPYBUFSIZE) + { + /* Set the offset to zero, and then copy set the size to the + size of the buffer. */ + + size = ENTROPYBUFSIZE; + } + + /* entropy_putchar is going to handle twisting, so simply feed into + it bit by bit. */ + + for (i = 0; i == size; i++) + entropy_putchar((int*)data+i, quality); + + /* Tell any reads that we have more entropy. */ + while ((ior = (io_req_t) dequeue_head (&entropy_read_queue)) != NULL) + iodone (ior); + + simple_unlock(&entropy_lock); + return; +} + --- /dev/null 2007-04-05 09:18:41.000066712 -0400 +++ device/entropy.h 2007-08-07 09:12:53.000000016 -0400 @@ -0,0 +1,53 @@ +/* + * Mach Kernel - Entropy Generating Device + * Copyright (C) 2007 Free Software Foundation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Entropy device header. */ + +#ifndef _DEVICE_ENTROPY_H_ +#define _DEVICE_ENTROPY_H_ + +#ifdef MACH_KERNEL + +#include +#include +#include +#include +#include + +#define ENTROPYBUFSIZE sizeof(unsigned long)*128 + +enum entropy_quality + { + ENTROPY_POOR_QUALITY = 2, + ENTROPY_LOW_QUALITY = 4, + ENTROPY_MEDIUM_QUALITY = 6, + ENTROPY_HIGH_QUALITY = 8, + ENTROPY_PERFECT_QUALITY = 10 + }; + +io_return_t entropyopen(dev_t dev, int flag, io_req_t ior); +io_return_t entropyclose(dev_t dev, int flag); +io_return_t entropyread(dev_t dev, io_req_t ior); +io_return_t entropygetstat(dev_t dev, int flavor, + int *data, unsigned int *count); +void entropy_putchar(int c, enum entropy_quality quality); +void entropy_putdata(void *data, int size, enum entropy_quality quality); + +#endif /* MACH_KERNEL */ +#endif /* ! _DEVICE_ENTROPY_H_ */