randomsound-0.2/COPYRIGHT0000644000000000000000000000216510661522375015354 0ustar00usergroup00000000000000This 'randomsound' tool is Copyright Daniel Silverstone 2007. It is provided under the terms of the licence below. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. randomsound-0.2/Changes0000644000000000000000000000027610661522375015355 0ustar00usergroup000000000000000.2 Incorporated manual page provided by Debian, updated it slightly. Added changes document. 0.1 Numbered release, added -V option Unnumbered release Initial release, fully functionalrandomsound-0.2/Makefile0000644000000000000000000000074210661522375015520 0ustar00usergroup00000000000000all: randomsound SRCS := randomsound.c bitbuffer.c debias.c asoundrunner.c HDRS := bitbuffer.h debias.h asoundrunner.h LINK := gcc CC := gcc OBJS := $(SRCS:.c=.o) check: test_bitbuffer randomsound: $(OBJS) $(LINK) -o $@ $^ clean: $(RM) randomsound $(OBJS) $(RM) *~ test_bitbuffer test_%: %.c $(CC) -DTEST -o $@ $< ./$@ randomsound.o: bitbuffer.h debias.h asoundrunner.h bitbuffer.o: bitbuffer.h debias.o: debias.h bitbuffer.h asoundrunner.o: asoundrunner.h bitbuffer.h randomsound-0.2/asoundrunner.c0000644000000000000000000000353610661522375016753 0ustar00usergroup00000000000000#include "asoundrunner.h" #include #include #include #include #include #include #include #define SAMPLERATE 8000 #define SAMPLERATESTR "8000" int arecord_read_fd = -1; int restart_arecord = 1; static BitBuffer read_into_here; static int signal_handler_installed = 0; void child_handler(int _ignored) { int status; while (waitpid(-1, &status, WNOHANG) != -1) ; restart_arecord = 1; } int start_arecord(BitBuffer read_into) { pid_t child; int pipefd[2]; int sparefd; read_into_here = read_into; if (signal_handler_installed == 0) { signal(SIGCHLD, child_handler); signal_handler_installed = 1; } if (arecord_read_fd != -1) { close(arecord_read_fd); arecord_read_fd = -1; } if (socketpair(AF_LOCAL, SOCK_STREAM, PF_LOCAL, pipefd) == -1) return -1; restart_arecord = 0; child = fork(); switch (child) { case -1: return -1; case 0: sparefd = open("/dev/null", O_RDWR); close(0); close(1); close(2); close(pipefd[0]); dup2(pipefd[1], 1); close(pipefd[1]); dup2(sparefd, 0); dup2(sparefd, 2); close(sparefd); execlp("arecord", "arecord", "-c", "1", "-f", "S16_LE", "-r", SAMPLERATESTR, "-t", "raw", NULL); exit(1); default: close(pipefd[1]); arecord_read_fd = pipefd[0]; } return child; } void asound_do_read(void) { /* Read in SAMPLERATE*2/10 bytes (1/10th of a second of sampling) */ BitField buffer[SAMPLERATE*5]; int xfered = 0; int readbytes = read(arecord_read_fd, buffer, SAMPLERATE*5); if (readbytes < 0) { perror("read"); restart_arecord = 1; return; } while (xfered < (readbytes>>1) && bitbuffer_free_space(read_into_here) > 0) { BitField thisbit = buffer[xfered]; bitbuffer_add_bits(read_into_here, thisbit, 8); xfered += 2; } } randomsound-0.2/asoundrunner.h0000644000000000000000000000034410661522375016752 0ustar00usergroup00000000000000#ifndef RANDOMSOUND_ASOUNDRUNNER_H #define RANDOMSOUND_ASOUNDRUNNER_H #include "bitbuffer.h" extern int arecord_read_fd; extern int restart_arecord; int start_arecord(BitBuffer read_into); void asound_do_read(void); #endif randomsound-0.2/bitbuffer.c0000644000000000000000000000766510661522375016207 0ustar00usergroup00000000000000/** @file bitbuffer.h * * Implementation of a circular buffer of bits. * * @author Daniel Silverstone */ #include #include "bitbuffer.h" #ifndef MIN #define MIN(a,b) (((a)<(b))?(a):(b)) #endif struct bitbuffer_s { int size; int firstused; int nextfree; int bitsused; BitField bits[0]; }; #define BYTE_FOR_BIT(n) (n>>3) #define SHIFT_FOR_BIT(n) (n&7) BitBuffer bitbuffer_new(const int size) { int bytesize = ((size + 7) & ~7) >> 3; BitBuffer ret = (BitBuffer)(malloc(sizeof(struct bitbuffer_s) + bytesize)); ret->size = size; ret->firstused = 0; ret->nextfree = 0; ret->bitsused = 0; return ret; } void bitbuffer_free(BitBuffer buf) { free(buf); } int bitbuffer_free_space(const BitBuffer buf) { return buf->size - buf->bitsused; } int bitbuffer_available_bits(const BitBuffer buf) { return buf->bitsused; } int bitbuffer_add_bits(BitBuffer buf, const BitField bits, int count) { int bits_to_add = MIN(MIN(8, count), bitbuffer_free_space(buf)); int i; for (i = 0; i < bits_to_add; ++i) { BitField subfield = buf->bits[BYTE_FOR_BIT(buf->nextfree)]; if (bits & (1<nextfree)); else subfield &= ~(1<nextfree)); buf->bits[BYTE_FOR_BIT(buf->nextfree++)] = subfield; if (buf->nextfree == buf->size) buf->nextfree = 0; } buf->bitsused += bits_to_add; return bits_to_add; } int bitbuffer_extract_bits(BitBuffer buf, BitField *bits, int count) { int bits_to_extract = MIN(MIN(8, count), bitbuffer_available_bits(buf)); int i; for (i = 0; i < bits_to_extract; ++i) { BitField subfield = buf->bits[BYTE_FOR_BIT(buf->firstused)]; if (subfield & (1<firstused++))) *bits |= (1<firstused == buf->size) buf->firstused = 0; } buf->bitsused -= bits_to_extract; return bits_to_extract; } #ifdef TEST #include void xassert(const char* msg, int val, int line, BitBuffer buf, BitField bits) { if (val == 0) { fprintf(stdout, "FAILURE on line %d of condition %s\n", line, msg); fprintf(stdout, "Buffer at %p: size %d firstused %d nextfree %d\n", buf, buf->size, buf->firstused, buf->nextfree); fprintf(stdout, "Bitfield is %02x\n", bits); exit(1); } } #ifdef assert #undef assert #endif #define assert(X) xassert(#X, X, __LINE__, buf, bits) int main(int argc, char** argv) { BitBuffer buf; BitField bits = 0xA5; buf = bitbuffer_new(32); assert(buf != NULL); assert(bitbuffer_free_space(buf) == 32); assert(bitbuffer_available_bits(buf) == 0); assert(bitbuffer_add_bits(buf, bits, 8) == 8); assert(bitbuffer_add_bits(buf, bits, 8) == 8); assert(bitbuffer_add_bits(buf, bits, 8) == 8); assert(bitbuffer_add_bits(buf, bits, 8) == 8); assert(bitbuffer_add_bits(buf, bits, 8) == 0); assert(bitbuffer_free_space(buf) == 0); assert(bitbuffer_available_bits(buf) == 32); assert(bitbuffer_extract_bits(buf, &bits, 8) == 8); assert(bits == 0xA5); assert(bitbuffer_extract_bits(buf, &bits, 8) == 8); assert(bits == 0xA5); assert(bitbuffer_extract_bits(buf, &bits, 8) == 8); assert(bits == 0xA5); assert(bitbuffer_extract_bits(buf, &bits, 8) == 8); assert(bits == 0xA5); assert(bitbuffer_extract_bits(buf, &bits, 8) == 0); bits = 0x96; assert(bitbuffer_add_bits(buf, bits, 8) == 8); bits = 0xF; assert(bitbuffer_add_bits(buf, bits, 4) == 4); bits = 0x96; assert(bitbuffer_add_bits(buf, bits, 8) == 8); bits = 0xF; assert(bitbuffer_add_bits(buf, bits, 4) == 4); assert(bitbuffer_extract_bits(buf, &bits, 8) == 8); assert(bits == 0x96); assert(bitbuffer_extract_bits(buf, &bits, 8) == 8); assert(bits == 0x6F); assert(bitbuffer_extract_bits(buf, &bits, 4) == 4); assert((bits & 0xf) == 0x9); assert(bitbuffer_extract_bits(buf, &bits, 8) == 4); assert((bits & 0xf) == 0xF); return 0; } #endif randomsound-0.2/bitbuffer.h0000644000000000000000000000454510661522375016206 0ustar00usergroup00000000000000/** @file bitbuffer.h * * A circular buffer of bits. * * @author Daniel Silverstone */ #ifndef RANDOMSOUND_BITBUFFER_H #define RANDOMSOUND_BITBUFFER_H /** A bit buffer. * * A circular buffer of a given number of bits. */ typedef struct bitbuffer_s *BitBuffer; /** A bit field, cunningly disguised as an unsigned char. */ typedef unsigned char BitField; /** Allocate a new bitbuffer. * * Given the \a size requested, create a new bit buffer which can store * that number of bits and return it having initialised it properly. * * @param size The number of bits to store in this buffer. * @return The new ::BitBuffer */ BitBuffer bitbuffer_new(const int size); /** Free a bit buffer. * * Free a bitbuffer and all associated storage. * * @param buf The ::BitBuffer to free. */ void bitbuffer_free(BitBuffer buf); /** Get free space in bit buffer. * * Return the number of free bits in \a buf. * * @param buf The ::BitBuffer in question. * @return The number of free bits in the buffer. */ int bitbuffer_free_space(const BitBuffer buf); /** Get the number of bits available for extraction. * * Return the number of bits stored in the buffer and which are thus * available for extraction. * * @param buf The ::BitBuffer in question * @return The number of bits available for extraction. */ int bitbuffer_available_bits(const BitBuffer buf); /** Store some bits into a buffer. * * Store \a count of bits out of \a bits into \s buf. * * This routine works least-significant-bit first so if you are only * storing one bit, make sure it's in bit zero of the ::BitField. * * @param buf The ::BitBuffer to add to. * @param bits The ::BitField to find the bits in. * @param count The number of bits to add to \a buf. * @return The number of bits actually added. */ int bitbuffer_add_bits(BitBuffer buf, const BitField bits, int count); /** Extract some bits from a buffer. * * Extract \a count of bits out of \a buf into \s bits. * * This routine works least-significant-bit first so if you are only * extracting one bit, it will be in bit zero of the ::BitField. * * @param buf The ::BitBuffer to extract from. * @param bits A pointer to a ::BitField to put the bits in. * @param count The number of bits to add to \a bits. * @return The number of bits actually added. */ int bitbuffer_extract_bits(BitBuffer buf, BitField *bits, int count); #endif randomsound-0.2/debias.c0000644000000000000000000000101210661522375015442 0ustar00usergroup00000000000000/** @file debias.c * * Implementation of a von-neumann debiassing of a random bitstream. */ #include "debias.h" int transfer_bits_and_debias(BitBuffer from, BitBuffer to) { BitField bits; int bits_xfered = 0; while (bitbuffer_available_bits(from) >= 2) { if (bitbuffer_extract_bits(from, &bits, 2) != 2) return bits_xfered; if ((bits & 3) == 1 || (bits & 3) == 2) { if (bitbuffer_add_bits(to, bits, 1) != 1) return bits_xfered; bits_xfered++; } } return bits_xfered; } randomsound-0.2/debias.h0000644000000000000000000000163010661522375015455 0ustar00usergroup00000000000000/** @file debias.h * * Perform a von-neumann debiassing of a random bitstream. */ #ifndef RANDOMSOUND_DEBIAS_H #define RANDOMSOUND_DEBIAS_H #include "bitbuffer.h" /** Transfer bits from one buffer to another, debiassing en-route. * * Performing a von-neumann debiassing, transfer bits from the \a from * ::BitBuffer to the \a to ::BitBuffer. * * This method of debiassing will produce at absolute maximum, a drop * of 50% in the bitcount. I.E. at minimum you will lose one bit in two. * * In actuality, in a truly random stream, you will lose three bits in * four, which means that the debiassing will leave you with around * one quarter the number of bits you started with. * * @param from The ::BitBuffer to extract bits from. * @param to The ::BitBuffer to add debiassed bits to. * @return The number of bits added to \a to. */ int transfer_bits_and_debias(BitBuffer from, BitBuffer to); #endif randomsound-0.2/randomsound.80000644000000000000000000000277410661522375016511 0ustar00usergroup00000000000000.TH RANDOMSOUND 8 "August 18, 2007" "Pepperfish" .SH NAME randomsound \- ALSA sound card related entropy gathering daemon. .SH SYNOPSIS .B randomsound [options] .SH DESCRIPTION .PP Using the low order bit of the ADC output of your sound card, \fBrandomsound\fP gathers entropy, debiases it and offers it up to your kernel's random pool. It can be tweaked to only write into the pool when it drops below a certain level, and to back off once the pool is full enough. This build will set your sound card into 16 bit mono unsigned input at 8KHz. If your sound card cannot do that then you will need to change the defines in asoundrunner.c and recompile the package. You must have set up asound as root on your machine. This can be done with the asoundconf tool and its set-default-card command. .PP You may also need to use the alsamixer to ensure that the sound card is generating plenty of noise. Set all the gains nice and high, turn on any boosters you have. If you have a V_REFLVL or similar then consider tweaking that. .SH OPTIONS .TP .B -D Daemonize .TP .B -v Increase verbosity. Can be used more than once. .TP .B -m specify minimum number of bits of entropy in the pool. .TP .B -M specify max number of bits in the pool. .TP .B -b specify number of bytes of randomness to buffer for use. .TP .B -d specify number of bytes to deposit into the pool each time. .TP .B -h display help message .TP .B -V display version information. .SH AUTHOR randomsound was written by Daniel Silverstone randomsound-0.2/randomsound.c0000644000000000000000000001453710661522375016564 0ustar00usergroup00000000000000#include #include #include #include #include #include #include #include #include #include "bitbuffer.h" #include "debias.h" #include "asoundrunner.h" static char *version_number = "0.2"; int daemonise = 0; int verbose = 0; int minwatermark = 256; int maxwatermark = 4096-256; int depositsize = 64; int buffersize = 64 * 16; BitBuffer incoming_bits; BitBuffer buffered_bits; int randomfd; struct injector { int ent_count; int size; union { int ints[128]; BitField bitfield[512]; } value; } random_injector; int bits_in_pool(void) { int ret; ioctl(randomfd, RNDGETENTCNT, &ret); return ret; } void do_mixin_bits(void) { int i; int bits_before = bits_in_pool(); if (verbose > 3) printf("Injecting %d bits of entropy into the kernel\n", depositsize * 8); random_injector.ent_count = depositsize * 8; random_injector.size = depositsize; for (i = 0; i < depositsize; ++i) { bitbuffer_extract_bits(buffered_bits, random_injector.value.bitfield + i, 8); } if (ioctl(randomfd, RNDADDENTROPY, &random_injector) == -1) { perror("ioctl"); } if (verbose > 3) printf("Kernel now at %d bits of entropy\n", bits_in_pool()); if (bits_before == bits_in_pool()) printf("Did it fail?!?!\n"); } void main_loop() { fd_set readfds; fd_set writefds; fd_set errfds; int ret; int adding = 0; FD_ZERO(&writefds); while (1) { if (restart_arecord == 1) { int pid; if (verbose > 1) printf("Need to restart arecord.\n"); pid = start_arecord(incoming_bits); if (pid == -1) return; if (verbose > 1) printf("Started arecord with pid %d\n", pid); FD_ZERO(&readfds); FD_ZERO(&errfds); if (restart_arecord) { printf("Arecord already died.\n"); return; } } FD_SET(arecord_read_fd, &readfds); FD_SET(arecord_read_fd, &errfds); ret = select(arecord_read_fd + 1, &readfds, &writefds, &errfds, NULL); if (ret == -1) { perror("select"); return; } if (FD_ISSET(arecord_read_fd, &readfds)) asound_do_read(); if (FD_ISSET(arecord_read_fd, &errfds)) { printf("Error on arecord fd, gotta restart.\n"); restart_arecord = 1; } ret = transfer_bits_and_debias(incoming_bits, buffered_bits); if (verbose > 3 && ret > 0) printf("Added %d bits to cache. Now at %d/%d bits in it\n", ret, bitbuffer_available_bits(buffered_bits), buffersize * 8); if (bits_in_pool() <= minwatermark && adding == 0) { if (verbose > 2) printf("Transition to inserting entropy. Kernel pool at %d\n", bits_in_pool()); adding = 1; } if (bits_in_pool() >= maxwatermark && adding == 1) { if (verbose > 2) printf("Transition to waiting. Kernel pool at %d\n", bits_in_pool()); adding = 0; } if (adding == 1) { if (bitbuffer_available_bits(buffered_bits) >= (depositsize * 8)) { do_mixin_bits(); if (verbose > 3) printf("Kernel entropy pool now sits at %d bits\n", bits_in_pool()); } } } } void usage(const char* prog, FILE *output) { fprintf(output, "%s: Usage:\n"\ "\n"\ "Argument: h - display this help message\n"\ " V - display version information.\n", " D - Daemonize\n"\ " v - Increase verbosity. Can be used more than once.\n"\ " m - specify minimum number of bits of entropy in the pool.\n"\ " M - specify max number of bits in the pool.\n"\ " b - specify number of bytes of randomness to buffer for use.\n"\ " d - specify number of bytes to deposit into the pool each time.\n", prog); } void version(const char* prog, FILE *output) { fprintf(output, "%s: %s\n"\ "Copyright 2007 Daniel Silverstone\n", prog, version_number); } int main(int argc, char **argv) { int opt; while ((opt = getopt(argc, argv, ":hDvVm:M:b:d:")) != -1) { switch (opt) { case 'h': usage(argv[0], stdout); return 0; case 'V': version(argv[0], stdout); return 0; case 'D': daemonise = 1; break; case 'v': verbose += 1; break; case 'm': minwatermark = atoi(optarg); break; case 'M': maxwatermark = atoi(optarg); break; case 'b': buffersize = atoi(optarg); break; case 'd': depositsize = atoi(optarg); break; default: usage(argv[0], stderr); return 1; } } /* Validate options now */ if (minwatermark < 64) { fprintf(stderr, "Minimum watermark is below 64 bits. This is silly.\n"); return 2; } if (maxwatermark > 4096) { fprintf(stderr, "Maxmimum watermark is above 4096. This is not possible.\n"); return 2; } if (buffersize < depositsize || buffersize > (1024*1024)) { fprintf(stderr, "Buffer size smaller than deposit size or greater than one megabyte.\n"); return 2; } if (depositsize < 4 || depositsize > 512 || (depositsize & 3) != 0) { fprintf(stderr, "Deposit size must be a multiple of four, between 4 and 512 inclusive.\n"); return 2; } if (verbose > 0) { printf("Random sound daemon. Copyright 2007 Daniel Silverstone.\n\n"); printf("Will keep random pool between %d and %d bits of entropy.\n", minwatermark, maxwatermark); printf("Will retain a buffer of %d bytes, making entropy deposits of %d bytes at a time.\n", buffersize, depositsize); if (daemonise == 1) { printf("Will daemonise.\n"); } } if (verbose > 1) { printf("Allocating a %d bit buffer for the incoming bits.\n", buffersize * 8 * 4); } incoming_bits = bitbuffer_new(buffersize * 8 * 4); buffered_bits = bitbuffer_new(buffersize * 8); if (incoming_bits == NULL || buffered_bits == NULL) { fprintf(stderr, "Unable to allocate buffers.\n"); return 3; } randomfd = open("/dev/random", O_RDWR); if (randomfd == -1) { perror("Opening /dev/random\n"); return 3; } if (daemonise == 1) { printf("Daemonising\n"); fflush(stdout); int fd = fork(); if (fd == -1 ) { perror("forking daemon.\n"); return 4; } if (fd != 0) return 0; setpgrp(); setsid(); } main_loop(); return -1; }