diff options
-rw-r--r-- | debian/patches/random0001-xxx-standalone-random-translator.patch | 3214 | ||||
-rw-r--r-- | debian/patches/series | 1 |
2 files changed, 0 insertions, 3215 deletions
diff --git a/debian/patches/random0001-xxx-standalone-random-translator.patch b/debian/patches/random0001-xxx-standalone-random-translator.patch deleted file mode 100644 index fe3bba2c..00000000 --- a/debian/patches/random0001-xxx-standalone-random-translator.patch +++ /dev/null @@ -1,3214 +0,0 @@ -From 1ea5ac6db5000a16eea08111478504599d3c3295 Mon Sep 17 00:00:00 2001 -From: Justus Winter <4winter@informatik.uni-hamburg.de> -Date: Thu, 12 Nov 2015 22:16:49 +0100 -Subject: [PATCH hurd] xxx standalone random translator - ---- - Makefile | 1 - - random/Makefile | 30 -- - random/TODO | 11 - - random/gnupg-bithelp.h | 41 --- - random/gnupg-glue.h | 40 --- - random/gnupg-random.c | 810 ------------------------------------------------- - random/gnupg-random.h | 47 --- - random/gnupg-rmd.h | 38 --- - random/gnupg-rmd160.c | 656 --------------------------------------- - random/random.c | 650 --------------------------------------- - random/random.h | 32 -- - sutils/MAKEDEV.sh | 6 +- - trans/Makefile | 7 +- - trans/random.c | 682 +++++++++++++++++++++++++++++++++++++++++ - 14 files changed, 691 insertions(+), 2360 deletions(-) - delete mode 100644 random/Makefile - delete mode 100644 random/TODO - delete mode 100644 random/gnupg-bithelp.h - delete mode 100644 random/gnupg-glue.h - delete mode 100644 random/gnupg-random.c - delete mode 100644 random/gnupg-random.h - delete mode 100644 random/gnupg-rmd.h - delete mode 100644 random/gnupg-rmd160.c - delete mode 100644 random/random.c - delete mode 100644 random/random.h - create mode 100644 trans/random.c - -diff --git a/Makefile b/Makefile -index 3178740..6544cd2 100644 ---- a/Makefile -+++ b/Makefile -@@ -38,7 +38,6 @@ prog-subdirs = auth proc exec term \ - hostmux usermux ftpfs trans \ - console-client utils sutils \ - benchmarks fstests \ -- random \ - procfs \ - startup \ - init \ -diff --git a/random/Makefile b/random/Makefile -deleted file mode 100644 -index 0949b63..0000000 ---- a/random/Makefile -+++ /dev/null -@@ -1,30 +0,0 @@ --# --# Copyright (C) 1994,95,96,97,99,2000,2001 Free Software Foundation, Inc. --# --# 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -- --dir := random --makemode := server -- --CFLAGS += -D__HURD__ -- --target = random --SRCS = random.c gnupg-random.c gnupg-rmd160.c --OBJS = $(SRCS:.c=.o) startup_notifyServer.o --LCLHDRS = gnupg-random.h gnupg-rmd.h gnupg-bithelp.h random.h --HURDLIBS = trivfs ports fshelp ihash shouldbeinlibc --OTHERLIBS = -lpthread -- --include ../Makeconf -diff --git a/random/TODO b/random/TODO -deleted file mode 100644 -index 9cc57ab..0000000 ---- a/random/TODO -+++ /dev/null -@@ -1,11 +0,0 @@ --* read_poll uses random_poll until the pool is filled. This is ian -- issue at first initialization, as this requries POOLSIZE good random (level 1 from -- gather_random) even in level 0 and 1. -- For now, the code is only applied to level 2. Eventually, readable_pool -- should be fixed to return 0 if initialization is not done yet and not enough bytes -- are available. Otherwise it enters an infinite loop. -- --* Permissions? -- --* Off by one error in gather_random/io_write? I can only get GATHERBUFSIZE - 1 -- bytes from it. -diff --git a/random/gnupg-bithelp.h b/random/gnupg-bithelp.h -deleted file mode 100644 -index 188db16..0000000 ---- a/random/gnupg-bithelp.h -+++ /dev/null -@@ -1,41 +0,0 @@ --/* bithelp.h - Some bit manipulation helpers -- * Copyright (C) 1999 Free Software Foundation, Inc. -- * -- * This file is part of GnuPG. -- * -- * GnuPG 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 of the License, or -- * (at your option) any later version. -- * -- * GnuPG 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, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA -- */ --#ifndef G10_BITHELP_H --#define G10_BITHELP_H -- -- --/**************** -- * Rotate a 32 bit integer by n bytes -- */ --#if defined(__GNUC__) && defined(__i386__) --static inline u32 --rol( u32 x, int n) --{ -- __asm__("roll %%cl,%0" -- :"=r" (x) -- :"0" (x),"c" (n)); -- return x; --} --#else -- #define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) ) --#endif -- -- --#endif /*G10_BITHELP_H*/ -diff --git a/random/gnupg-glue.h b/random/gnupg-glue.h -deleted file mode 100644 -index cbf0a10..0000000 ---- a/random/gnupg-glue.h -+++ /dev/null -@@ -1,40 +0,0 @@ --#ifndef __GNUPG_GLUE_H__ --#define __GNUPG_GLUE_H__ -- --#include <sys/types.h> --#include <random.h> -- --#define SIZEOF_UNSIGNED_LONG 4 --typedef unsigned int u32; --typedef unsigned char byte; -- --/* GnuPG's config.h */ --#define HAVE_GETTIMEOFDAY 1 --#define HAVE_GETRUSAGE 1 --#define HAVE_RAND 1 -- --/* GnuPG's memory.h */ --#define m_alloc malloc --#define m_alloc_secure malloc --#define m_alloc_clear(x) calloc(x, 1) --#define m_alloc_secure_clear(x) calloc(x, 1) --#define m_free free --#define m_strdup strdup -- --/* GnuPG's dynaload.h */ --#define dynload_getfnc_fast_random_poll() (0) --#define dynload_getfnc_gather_random() &gather_random --int --gather_random( void (*add)(const void*, size_t, int), int requester, -- size_t length, int level ); -- --/* GnuPG's miscellaneous stuff. */ --#define BUG() assert(0) --#define _(x) x --#define make_timestamp() time(0) --#define tty_printf printf --#define log_info(format, args...) printf(format , ## args) --#define log_fatal(format, args...) { printf(format , ## args) ; exit(2); } --#define DIM(v) (sizeof(v)/sizeof((v)[0])) -- --#endif /* __GNUPG_GLUE_H__ */ -diff --git a/random/gnupg-random.c b/random/gnupg-random.c -deleted file mode 100644 -index 54ee3c5..0000000 ---- a/random/gnupg-random.c -+++ /dev/null -@@ -1,810 +0,0 @@ --/* random.c - random number generator -- * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. -- * -- * This file is part of GnuPG. -- * -- * GnuPG 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 of the License, or -- * (at your option) any later version. -- * -- * GnuPG 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, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA -- */ -- -- --/**************** -- * This random number generator is modelled after the one described -- * in Peter Gutmann's Paper: "Software Generation of Practically -- * Strong Random Numbers". -- */ -- --#ifndef __HURD__ --#include <config.h> --#else --#include "gnupg-glue.h" --#endif --#include <stdio.h> --#include <stdlib.h> --#include <assert.h> --#include <errno.h> --#include <string.h> --#include <time.h> --#include <sys/time.h> --#include <sys/types.h> --#include <sys/stat.h> --#include <unistd.h> --#include <fcntl.h> --#ifdef HAVE_GETHRTIME -- #include <sys/times.h> --#endif --#ifdef HAVE_GETTIMEOFDAY -- #include <sys/times.h> --#endif --#ifdef HAVE_GETRUSAGE -- #include <sys/resource.h> --#endif --#ifdef __MINGW32__ -- #include <process.h> --#endif --#ifndef __HURD__ --#include "util.h" --#endif --#ifndef __HURD__ --#include "rmd.h" --#include "ttyio.h" --#include "i18n.h" --#include "random.h" --#include "rand-internal.h" --#include "dynload.h" --#else --#include "gnupg-rmd.h" --#include "gnupg-random.h" --#endif -- --#ifndef RAND_MAX /* for SunOS */ -- #define RAND_MAX 32767 --#endif -- -- --#if SIZEOF_UNSIGNED_LONG == 8 -- #define ADD_VALUE 0xa5a5a5a5a5a5a5a5 --#elif SIZEOF_UNSIGNED_LONG == 4 -- #define ADD_VALUE 0xa5a5a5a5 --#else -- #error weird size for an unsigned long --#endif -- --#define BLOCKLEN 64 /* hash this amount of bytes */ --#define DIGESTLEN 20 /* into a digest of this length (rmd160) */ --/* poolblocks is the number of digests which make up the pool -- * and poolsize must be a multiple of the digest length -- * to make the AND operations faster, the size should also be -- * a multiple of ulong -- */ --#define POOLBLOCKS 30 --#define POOLSIZE (POOLBLOCKS*DIGESTLEN) --#if (POOLSIZE % SIZEOF_UNSIGNED_LONG) -- #error Please make sure that poolsize is a multiple of ulong --#endif --#define POOLWORDS (POOLSIZE / SIZEOF_UNSIGNED_LONG) -- -- --static int is_initialized; --#define MASK_LEVEL(a) do {if( a > 2 ) a = 2; else if( a < 0 ) a = 0; } while(0) --static char *rndpool; /* allocated size is POOLSIZE+BLOCKLEN */ --static char *keypool; /* allocated size is POOLSIZE+BLOCKLEN */ --static size_t pool_readpos; --static size_t pool_writepos; --static int pool_filled; --static int pool_balance; --static int just_mixed; --static int did_initial_extra_seeding; --static char *seed_file_name; --static int allow_seed_file_update; -- --static int secure_alloc; --static int quick_test; --static int faked_rng; -- -- --#ifndef __HURD__ --static void read_pool( byte *buffer, size_t length, int level ); --#else --int read_pool( byte *buffer, size_t length, int level ); --#endif --static void add_randomness( const void *buffer, size_t length, int source ); --static void random_poll(void); --#ifndef __HURD__ --static void read_random_source( int requester, size_t length, int level); --#else --static int read_random_source( int requester, size_t length, int level); --#endif --static int gather_faked( void (*add)(const void*, size_t, int), int requester, -- size_t length, int level ); -- --static struct { -- ulong mixrnd; -- ulong mixkey; -- ulong slowpolls; -- ulong fastpolls; -- ulong getbytes1; -- ulong ngetbytes1; -- ulong getbytes2; -- ulong ngetbytes2; -- ulong addbytes; -- ulong naddbytes; --} rndstats; -- --static void --initialize(void) --{ -- /* The data buffer is allocated somewhat larger, so that -- * we can use this extra space (which is allocated in secure memory) -- * as a temporary hash buffer */ -- rndpool = secure_alloc ? m_alloc_secure_clear(POOLSIZE+BLOCKLEN) -- : m_alloc_clear(POOLSIZE+BLOCKLEN); -- keypool = secure_alloc ? m_alloc_secure_clear(POOLSIZE+BLOCKLEN) -- : m_alloc_clear(POOLSIZE+BLOCKLEN); -- is_initialized = 1; --#ifndef __HURD__ -- cipher_modules_constructor(); --#endif --} -- --static void --burn_stack (int bytes) --{ -- char buf[128]; -- -- memset (buf, 0, sizeof buf); -- bytes -= sizeof buf; -- if (bytes > 0) -- burn_stack (bytes); --} -- --void --random_dump_stats() --{ -- fprintf(stderr, -- "random usage: poolsize=%d mixed=%lu polls=%lu/%lu added=%lu/%lu\n" -- " outmix=%lu getlvl1=%lu/%lu getlvl2=%lu/%lu\n", -- POOLSIZE, rndstats.mixrnd, rndstats.slowpolls, rndstats.fastpolls, -- rndstats.naddbytes, rndstats.addbytes, -- rndstats.mixkey, rndstats.ngetbytes1, rndstats.getbytes1, -- rndstats.ngetbytes2, rndstats.getbytes2 ); --} -- --void --secure_random_alloc() --{ -- secure_alloc = 1; --} -- -- --int --quick_random_gen( int onoff ) --{ -- int last; -- -- read_random_source(0,0,0); /* init */ -- last = quick_test; -- if( onoff != -1 ) -- quick_test = onoff; -- return faked_rng? 1 : last; --} -- -- --/**************** -- * Fill the buffer with LENGTH bytes of cryptographically strong -- * random bytes. level 0 is not very strong, 1 is strong enough -- * for most usage, 2 is good for key generation stuff but may be very slow. -- */ --void --randomize_buffer( byte *buffer, size_t length, int level ) --{ -- char *p = get_random_bits( length*8, level, 1 ); -- memcpy( buffer, p, length ); -- m_free(p); --} -- -- --int --random_is_faked() --{ -- if( !is_initialized ) -- initialize(); -- return faked_rng || quick_test; --} -- --/**************** -- * Return a pointer to a randomized buffer of level 0 and LENGTH bits -- * caller must free the buffer. -- * Note: The returned value is rounded up to bytes. -- */ --byte * --get_random_bits( size_t nbits, int level, int secure ) --{ -- byte *buf, *p; -- size_t nbytes = (nbits+7)/8; -- -- if( quick_test && level > 1 ) -- level = 1; -- MASK_LEVEL(level); -- if( level == 1 ) { -- rndstats.getbytes1 += nbytes; -- rndstats.ngetbytes1++; -- } -- else if( level >= 2 ) { -- rndstats.getbytes2 += nbytes; -- rndstats.ngetbytes2++; -- } -- -- buf = secure && secure_alloc ? m_alloc_secure( nbytes ) : m_alloc( nbytes ); -- for( p = buf; nbytes > 0; ) { -- size_t n = nbytes > POOLSIZE? POOLSIZE : nbytes; --#ifdef __HURD__ -- n = --#endif -- read_pool( p, n, level ); -- nbytes -= n; -- p += n; -- -- } -- return buf; --} -- -- --/**************** -- * Mix the pool -- */ --static void --mix_pool(byte *pool) --{ -- char *hashbuf = pool + POOLSIZE; -- char *p, *pend; -- int i, n; -- RMD160_CONTEXT md; -- -- rmd160_init( &md ); -- #if DIGESTLEN != 20 -- #error must have a digest length of 20 for ripe-md-160 -- #endif -- /* loop over the pool */ -- pend = pool + POOLSIZE; -- memcpy(hashbuf, pend - DIGESTLEN, DIGESTLEN ); -- memcpy(hashbuf+DIGESTLEN, pool, BLOCKLEN-DIGESTLEN); -- rmd160_mixblock( &md, hashbuf); -- memcpy(pool, hashbuf, 20 ); -- -- p = pool; -- for( n=1; n < POOLBLOCKS; n++ ) { -- memcpy(hashbuf, p, DIGESTLEN ); -- -- p += DIGESTLEN; -- if( p+DIGESTLEN+BLOCKLEN < pend ) -- memcpy(hashbuf+DIGESTLEN, p+DIGESTLEN, BLOCKLEN-DIGESTLEN); -- else { -- char *pp = p+DIGESTLEN; -- for(i=DIGESTLEN; i < BLOCKLEN; i++ ) { -- if( pp >= pend ) -- pp = pool; -- hashbuf[i] = *pp++; -- } -- } -- -- rmd160_mixblock( &md, hashbuf); -- memcpy(p, hashbuf, 20 ); -- } -- burn_stack (200); /* for the rmd160_mixblock() */ --} -- -- --void --set_random_seed_file( const char *name ) --{ -- if( seed_file_name ) -- BUG(); -- seed_file_name = m_strdup( name ); --} -- --/**************** -- * Read in a seed form the random_seed file -- * and return true if this was successful -- */ --static int --read_seed_file() --{ -- int fd; -- struct stat sb; -- unsigned char buffer[POOLSIZE]; -- int n; -- -- if( !seed_file_name ) -- return 0; -- -- #ifdef HAVE_DOSISH_SYSTEM -- fd = open( seed_file_name, O_RDONLY | O_BINARY ); -- #else -- fd = open( seed_file_name, O_RDONLY ); -- #endif -- if( fd == -1 && errno == ENOENT) { -- allow_seed_file_update = 1; -- return 0; -- } -- -- if( fd == -1 ) { -- log_info(_("can't open `%s': %s\n"), seed_file_name, strerror(errno) ); -- return 0; -- } -- if( fstat( fd, &sb ) ) { -- log_info(_("can't stat `%s': %s\n"), seed_file_name, strerror(errno) ); -- close(fd); -- return 0; -- } -- if( !S_ISREG(sb.st_mode) ) { -- log_info(_("`%s' is not a regular file - ignored\n"), seed_file_name ); -- close(fd); -- return 0; -- } -- if( !sb.st_size ) { -- log_info(_("note: random_seed file is empty\n") ); -- close(fd); -- allow_seed_file_update = 1; -- return 0; -- } -- if( sb.st_size != POOLSIZE ) { -- log_info(_("warning: invalid size of random_seed file - not used\n") ); -- close(fd); -- return 0; -- } -- do { -- n = read( fd, buffer, POOLSIZE ); -- } while( n == -1 && errno == EINTR ); -- if( n != POOLSIZE ) { -- log_fatal(_("can't read `%s': %s\n"), seed_file_name,strerror(errno) ); -- close(fd); -- return 0; -- } -- -- close(fd); -- -- add_randomness( buffer, POOLSIZE, 0 ); -- /* add some minor entropy to the pool now (this will also force a mixing) */ -- { pid_t x = getpid(); -- add_randomness( &x, sizeof(x), 0 ); -- } -- { time_t x = time(NULL); -- add_randomness( &x, sizeof(x), 0 ); -- } -- { clock_t x = clock(); -- add_randomness( &x, sizeof(x), 0 ); -- } -- /* And read a few bytes from our entropy source. By using -- * a level of 0 this will not block and might not return anything -- * with some entropy drivers, however the rndlinux driver will use -- * /dev/urandom and return some stuff - Do not read to much as we -- * want to be friendly to the scare system entropy resource. */ -- read_random_source( 0, 16, 0 ); -- -- allow_seed_file_update = 1; -- return 1; --} -- --void --update_random_seed_file() --{ -- ulong *sp, *dp; -- int fd, i; -- -- if( !seed_file_name || !is_initialized || !pool_filled ) -- return; -- if( !allow_seed_file_update ) { -- log_info(_("note: random_seed file not updated\n")); -- return; -- } -- -- -- /* copy the entropy pool to a scratch pool and mix both of them */ -- for(i=0,dp=(ulong*)keypool, sp=(ulong*)rndpool; -- i < POOLWORDS; i++, dp++, sp++ ) { -- *dp = *sp + ADD_VALUE; -- } -- mix_pool(rndpool); rndstats.mixrnd++; -- mix_pool(keypool); rndstats.mixkey++; -- -- #ifdef HAVE_DOSISH_SYSTEM -- fd = open( seed_file_name, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, -- S_IRUSR|S_IWUSR ); -- #else -- fd = open( seed_file_name, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR ); -- #endif -- if( fd == -1 ) { -- log_info(_("can't create `%s': %s\n"), seed_file_name, strerror(errno) ); -- return; -- } -- do { -- i = write( fd, keypool, POOLSIZE ); -- } while( i == -1 && errno == EINTR ); -- if( i != POOLSIZE ) { -- log_info(_("can't write `%s': %s\n"), seed_file_name, strerror(errno) ); -- } -- if( close(fd) ) -- log_info(_("can't close `%s': %s\n"), seed_file_name, strerror(errno) ); --} -- --#ifdef __HURD__ --int readable_pool( size_t length, int level ) --{ -- size_t needed = 0; -- size_t my_balance = pool_balance; -- size_t available = (gatherwpos - gatherrpos + GATHERBUFSIZE) % GATHERBUFSIZE; -- -- if (length > POOLSIZE) -- length = POOLSIZE; -- -- if (level < 2) -- return length; -- -- if( !pool_filled ) { -- if( read_seed_file() ) -- pool_filled = 1; -- } -- -- if (!did_initial_extra_seeding) -- { -- /* Take account for initial extra seeding. */ -- needed = length; -- if (needed < POOLSIZE/2) -- needed = POOLSIZE/2; -- my_balance = needed; -- -- if (!pool_filled && pool_writepos + needed < POOLSIZE) -- { -- /* If the pool is not filled yet, we couldn't read the seed -- file. Too bad. We will now have to take account for so many -- random_poll()s as fit into the remaining pool. */ -- -- needed += (POOLSIZE - pool_writepos + needed + POOLSIZE/5 - 1) / (POOLSIZE/5); -- } -- } -- else -- { -- if (!pool_filled) -- needed += (POOLSIZE - pool_writepos + needed + POOLSIZE/5 - 1) / (POOLSIZE/5); -- } -- -- /* NEEDED contains the bytes needed for initialization, MY_BALANCE the resulting -- available bytes. */ -- if (available < needed) -- return 0; -- return available + my_balance - needed; --} --#endif -- --#ifndef __HURD__ --static void --#else --int --#endif --read_pool( byte *buffer, size_t length, int level ) --{ -- int i; -- ulong *sp, *dp; -- -- if( length > POOLSIZE ) { --#ifndef __HURD__ -- log_fatal(_("too many random bits requested; the limit is %d\n"), -- POOLSIZE*8-1 ); --#else -- length = POOLSIZE; --#endif -- } -- -- if( !pool_filled ) { -- if( read_seed_file() ) -- pool_filled = 1; -- } -- -- /* For level 2 quality (key generation) we alwas make -- * sure that the pool has been seeded enough initially */ -- if( level == 2 && !did_initial_extra_seeding ) { -- size_t needed; -- -- pool_balance = 0; -- needed = length - pool_balance; -- if( needed < POOLSIZE/2 ) -- needed = POOLSIZE/2; -- else if( needed > POOLSIZE ) -- BUG(); --#ifdef __HURD__ -- needed = --#endif -- read_random_source( 3, needed, 2 ); --#ifdef __HURD__ -- if (! needed) -- return 0; -- /* XXX This will succeed with needed < POOLSIZE/2 even. But -- erroring out will waste the random we already got. */ --#endif -- pool_balance += needed; -- did_initial_extra_seeding=1; -- } -- -- /* for level 2 make sure that there is enough random in the pool */ -- if( level == 2 && pool_balance < length ) { -- size_t needed; -- -- if( pool_balance < 0 ) -- pool_balance = 0; -- needed = length - pool_balance; -- if( needed > POOLSIZE ) -- BUG(); --#ifdef __HURD__ -- needed = --#endif -- read_random_source( 3, needed, 2 ); -- pool_balance += needed; -- } -- --#ifdef __HURD__ -- /* XXX This makes level 0 and 1 worse than needed at first start up. */ -- if (level == 2) --#endif -- /* make sure the pool is filled */ -- while( !pool_filled ) -- random_poll(); -- -- /* do always a fast random poll */ -- fast_random_poll(); -- -- if( !level ) { /* no need for cryptographic strong random */ -- /* create a new pool */ -- for(i=0,dp=(ulong*)keypool, sp=(ulong*)rndpool; -- i < POOLWORDS; i++, dp++, sp++ ) -- *dp = *sp + ADD_VALUE; -- /* must mix both pools */ -- mix_pool(rndpool); rndstats.mixrnd++; -- mix_pool(keypool); rndstats.mixkey++; -- memcpy( buffer, keypool, length ); -- return length; -- } -- else { --#ifdef __HURD__ -- int amount; --#endif -- /* mix the pool (if add_randomness() didn't it) */ -- if( !just_mixed ) { -- mix_pool(rndpool); -- rndstats.mixrnd++; -- } -- /* create a new pool */ -- for(i=0,dp=(ulong*)keypool, sp=(ulong*)rndpool; -- i < POOLWORDS; i++, dp++, sp++ ) -- *dp = *sp + ADD_VALUE; -- /* and mix both pools */ -- mix_pool(rndpool); rndstats.mixrnd++; -- mix_pool(keypool); rndstats.mixkey++; -- /* read the required data -- * we use a readpointer to read from a different position each -- * time */ --#ifdef __HURD__ -- if (level == 2 && length > pool_balance) -- length = pool_balance; -- amount = length; --#endif -- while( length-- ) { -- *buffer++ = keypool[pool_readpos++]; -- if( pool_readpos >= POOLSIZE ) -- pool_readpos = 0; -- pool_balance--; -- } -- if( pool_balance < 0 ) -- pool_balance = 0; -- /* and clear the keypool */ -- memset( keypool, 0, POOLSIZE ); --#ifdef __HURD__ -- return amount; --#endif -- } --} -- -- --/**************** -- * Add LENGTH bytes of randomness from buffer to the pool. -- * source may be used to specify the randomness source. -- * Source is: -- * 0 - used ony for initialization -- * 1 - fast random poll function -- * 2 - normal poll function -- * 3 - used when level 2 random quality has been requested -- * to do an extra pool seed. -- */ --static void --add_randomness( const void *buffer, size_t length, int source ) --{ -- const byte *p = buffer; -- -- if( !is_initialized ) -- initialize(); -- rndstats.addbytes += length; -- rndstats.naddbytes++; -- while( length-- ) { -- rndpool[pool_writepos++] = *p++; -- if( pool_writepos >= POOLSIZE ) { -- if( source > 1 ) -- pool_filled = 1; -- pool_writepos = 0; -- mix_pool(rndpool); rndstats.mixrnd++; -- just_mixed = !length; -- } -- } --} -- -- -- --static void --random_poll() --{ -- rndstats.slowpolls++; -- read_random_source( 2, POOLSIZE/5, 1 ); --} -- -- --void --fast_random_poll() --{ -- static void (*fnc)( void (*)(const void*, size_t, int), int) = NULL; -- static int initialized = 0; -- -- rndstats.fastpolls++; -- if( !initialized ) { -- if( !is_initialized ) -- initialize(); -- initialized = 1; -- fnc = dynload_getfnc_fast_random_poll(); -- } -- if( fnc ) { -- (*fnc)( add_randomness, 1 ); -- return; -- } -- -- /* fall back to the generic function */ -- #if HAVE_GETHRTIME -- { hrtime_t tv; -- tv = gethrtime(); -- add_randomness( &tv, sizeof(tv), 1 ); -- } -- #elif HAVE_GETTIMEOFDAY -- { struct timeval tv; -- if( gettimeofday( &tv, NULL ) ) -- BUG(); -- add_randomness( &tv.tv_sec, sizeof(tv.tv_sec), 1 ); -- add_randomness( &tv.tv_usec, sizeof(tv.tv_usec), 1 ); -- } -- #elif HAVE_CLOCK_GETTIME -- { struct timespec tv; -- if( clock_gettime( CLOCK_REALTIME, &tv ) == -1 ) -- BUG(); -- add_randomness( &tv.tv_sec, sizeof(tv.tv_sec), 1 ); -- add_randomness( &tv.tv_nsec, sizeof(tv.tv_nsec), 1 ); -- } -- #else /* use times */ -- #ifndef HAVE_DOSISH_SYSTEM -- { struct tms buf; -- times( &buf ); -- add_randomness( &buf, sizeof buf, 1 ); -- } -- #endif -- #endif -- #ifdef HAVE_GETRUSAGE -- #ifndef RUSAGE_SELF -- #ifdef __GCC__ -- #warning There is no RUSAGE_SELF on this system -- #endif -- #else -- { struct rusage buf; -- /* QNX/Neutrino does return ENOSYS - so we just ignore it and -- * add whatever is in buf. In a chroot environment it might not -- * work at all (i.e. because /proc/ is not accessible), so we better -- * ognore all error codes and hope for the best -- */ -- getrusage( RUSAGE_SELF, &buf ); -- -- add_randomness( &buf, sizeof buf, 1 ); -- memset( &buf, 0, sizeof buf ); -- } -- #endif -- #endif -- /* time and clock are available on all systems - so -- * we better do it just in case one of the above functions -- * didn't work */ -- { time_t x = time(NULL); -- add_randomness( &x, sizeof(x), 1 ); -- } -- { clock_t x = clock(); -- add_randomness( &x, sizeof(x), 1 ); -- } --} -- -- --#ifndef __HURD__ --static void --#else --static int --#endif --read_random_source( int requester, size_t length, int level ) --{ -- static int (*fnc)(void (*)(const void*, size_t, int), int, -- size_t, int) = NULL; --#ifdef __HURD__ -- int got; --#endif -- if( !fnc ) { -- if( !is_initialized ) -- initialize(); -- fnc = dynload_getfnc_gather_random(); -- if( !fnc ) { -- faked_rng = 1; -- fnc = gather_faked; -- } -- if( !requester && !length && !level ) --#ifndef __HURD__ -- return; /* init only */ --#else -- return 0; --#endif -- } --#ifndef __HURD__ -- if( (*fnc)( add_randomness, requester, length, level ) < 0 ) -- log_fatal("No way to gather entropy for the RNG\n"); --#else -- got = (*fnc)( add_randomness, requester, length, level ); -- if (got < 0) -- log_fatal("No way to gather entropy for the RNG\n"); -- return got; --#endif --} -- -- --static int --gather_faked( void (*add)(const void*, size_t, int), int requester, -- size_t length, int level ) --{ -- static int initialized=0; -- size_t n; -- char *buffer, *p; -- -- if( !initialized ) { -- log_info(_("WARNING: using insecure random number generator!!\n")); -- tty_printf(_("The random number generator is only a kludge to let\n" -- "it run - it is in no way a strong RNG!\n\n" -- "DON'T USE ANY DATA GENERATED BY THIS PROGRAM!!\n\n")); -- initialized=1; -- #ifdef HAVE_RAND -- srand(make_timestamp()*getpid()); -- #else -- srandom(make_timestamp()*getpid()); -- #endif -- } -- printf("WAITING FOR %i bytes.\n", length); -- p = buffer = m_alloc( length ); -- n = length; -- #ifdef HAVE_RAND -- while( n-- ) -- *p++ = ((unsigned)(1 + (int) (256.0*rand()/(RAND_MAX+1.0)))-1); -- #else -- while( n-- ) -- *p++ = ((unsigned)(1 + (int) (256.0*random()/(RAND_MAX+1.0)))-1); -- #endif -- add_randomness( buffer, length, requester ); -- m_free(buffer); -- return 0; /* okay */ --} -- -diff --git a/random/gnupg-random.h b/random/gnupg-random.h -deleted file mode 100644 -index ee18feb..0000000 ---- a/random/gnupg-random.h -+++ /dev/null -@@ -1,47 +0,0 @@ --/* random.h - random functions -- * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. -- * -- * This file is part of GnuPG. -- * -- * GnuPG 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 of the License, or -- * (at your option) any later version. -- * -- * GnuPG 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, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA -- */ --#ifndef G10_RANDOM_H --#define G10_RANDOM_H -- --#ifndef __HURD__ --#include "types.h" --#else --#include "gnupg-glue.h" --int read_pool (byte *, size_t, int); --int readable_pool (size_t, int); --#endif -- --/*-- random.c --*/ --void random_dump_stats(void); --void secure_random_alloc(void); --void set_random_seed_file(const char *); --void update_random_seed_file(void); --int quick_random_gen( int onoff ); --int random_is_faked(void); --void randomize_buffer( byte *buffer, size_t length, int level ); --byte *get_random_bits( size_t nbits, int level, int secure ); --void fast_random_poll( void ); -- --/*-- rndw32.c --*/ --#ifdef USE_STATIC_RNDW32 --void rndw32_set_dll_name( const char *name ); --#endif -- --#endif /*G10_RANDOM_H*/ -diff --git a/random/gnupg-rmd.h b/random/gnupg-rmd.h -deleted file mode 100644 -index 2446fc7..0000000 ---- a/random/gnupg-rmd.h -+++ /dev/null -@@ -1,38 +0,0 @@ --/* rmd.h - RIPE-MD hash functions -- * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. -- * -- * This file is part of GnuPG. -- * -- * GnuPG 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 of the License, or -- * (at your option) any later version. -- * -- * GnuPG 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, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA -- */ --#ifndef G10_RMD_H --#define G10_RMD_H -- --#ifdef __HURD__ --#include "gnupg-glue.h" --#endif -- --/* we need this here because random.c must have direct access */ --typedef struct { -- u32 h0,h1,h2,h3,h4; -- u32 nblocks; -- byte buf[64]; -- int count; --} RMD160_CONTEXT; -- --void rmd160_init( RMD160_CONTEXT *hd ); --void rmd160_mixblock( RMD160_CONTEXT *hd, char *buffer ); -- --#endif /*G10_RMD_H*/ -diff --git a/random/gnupg-rmd160.c b/random/gnupg-rmd160.c -deleted file mode 100644 -index 6610768..0000000 ---- a/random/gnupg-rmd160.c -+++ /dev/null -@@ -1,656 +0,0 @@ --/* rmd160.c - RIPE-MD160 -- * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. -- * -- * This file is part of GnuPG. -- * -- * GnuPG 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 of the License, or -- * (at your option) any later version. -- * -- * GnuPG 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, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA -- */ -- --#ifndef __HURD__ --#include <config.h> --#endif --#include <stdio.h> --#include <stdlib.h> --#include <string.h> --#include <assert.h> --#ifndef __HURD__ --#include "util.h" --#include "memory.h" --#include "rmd.h" --#include "cipher.h" /* only used for the rmd160_hash_buffer() prototype */ --#include "dynload.h" -- --#include "bithelp.h" --#else --#include "gnupg-rmd.h" --#include "gnupg-bithelp.h" --#endif -- -- --/********************************* -- * RIPEMD-160 is not patented, see (as of 25.10.97) -- * http://www.esat.kuleuven.ac.be/~bosselae/ripemd160.html -- * Note that the code uses Little Endian byteorder, which is good for -- * 386 etc, but we must add some conversion when used on a big endian box. -- * -- * -- * Pseudo-code for RIPEMD-160 -- * -- * RIPEMD-160 is an iterative hash function that operates on 32-bit words. -- * The round function takes as input a 5-word chaining variable and a 16-word -- * message block and maps this to a new chaining variable. All operations are -- * defined on 32-bit words. Padding is identical to that of MD4. -- * -- * -- * RIPEMD-160: definitions -- * -- * -- * nonlinear functions at bit level: exor, mux, -, mux, - -- * -- * f(j, x, y, z) = x XOR y XOR z (0 <= j <= 15) -- * f(j, x, y, z) = (x AND y) OR (NOT(x) AND z) (16 <= j <= 31) -- * f(j, x, y, z) = (x OR NOT(y)) XOR z (32 <= j <= 47) -- * f(j, x, y, z) = (x AND z) OR (y AND NOT(z)) (48 <= j <= 63) -- * f(j, x, y, z) = x XOR (y OR NOT(z)) (64 <= j <= 79) -- * -- * -- * added constants (hexadecimal) -- * -- * K(j) = 0x00000000 (0 <= j <= 15) -- * K(j) = 0x5A827999 (16 <= j <= 31) int(2**30 x sqrt(2)) -- * K(j) = 0x6ED9EBA1 (32 <= j <= 47) int(2**30 x sqrt(3)) -- * K(j) = 0x8F1BBCDC (48 <= j <= 63) int(2**30 x sqrt(5)) -- * K(j) = 0xA953FD4E (64 <= j <= 79) int(2**30 x sqrt(7)) -- * K'(j) = 0x50A28BE6 (0 <= j <= 15) int(2**30 x cbrt(2)) -- * K'(j) = 0x5C4DD124 (16 <= j <= 31) int(2**30 x cbrt(3)) -- * K'(j) = 0x6D703EF3 (32 <= j <= 47) int(2**30 x cbrt(5)) -- * K'(j) = 0x7A6D76E9 (48 <= j <= 63) int(2**30 x cbrt(7)) -- * K'(j) = 0x00000000 (64 <= j <= 79) -- * -- * -- * selection of message word -- * -- * r(j) = j (0 <= j <= 15) -- * r(16..31) = 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8 -- * r(32..47) = 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12 -- * r(48..63) = 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2 -- * r(64..79) = 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 -- * r0(0..15) = 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12 -- * r0(16..31)= 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2 -- * r0(32..47)= 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13 -- * r0(48..63)= 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14 -- * r0(64..79)= 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 -- * -- * -- * amount for rotate left (rol) -- * -- * s(0..15) = 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8 -- * s(16..31) = 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12 -- * s(32..47) = 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5 -- * s(48..63) = 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12 -- * s(64..79) = 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 -- * s'(0..15) = 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6 -- * s'(16..31)= 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11 -- * s'(32..47)= 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5 -- * s'(48..63)= 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8 -- * s'(64..79)= 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 -- * -- * -- * initial value (hexadecimal) -- * -- * h0 = 0x67452301; h1 = 0xEFCDAB89; h2 = 0x98BADCFE; h3 = 0x10325476; -- * h4 = 0xC3D2E1F0; -- * -- * -- * RIPEMD-160: pseudo-code -- * -- * It is assumed that the message after padding consists of t 16-word blocks -- * that will be denoted with X[i][j], with 0 <= i <= t-1 and 0 <= j <= 15. -- * The symbol [+] denotes addition modulo 2**32 and rol_s denotes cyclic left -- * shift (rotate) over s positions. -- * -- * -- * for i := 0 to t-1 { -- * A := h0; B := h1; C := h2; D = h3; E = h4; -- * A' := h0; B' := h1; C' := h2; D' = h3; E' = h4; -- * for j := 0 to 79 { -- * T := rol_s(j)(A [+] f(j, B, C, D) [+] X[i][r(j)] [+] K(j)) [+] E; -- * A := E; E := D; D := rol_10(C); C := B; B := T; -- * T := rol_s'(j)(A' [+] f(79-j, B', C', D') [+] X[i][r'(j)] -- [+] K'(j)) [+] E'; -- * A' := E'; E' := D'; D' := rol_10(C'); C' := B'; B' := T; -- * } -- * T := h1 [+] C [+] D'; h1 := h2 [+] D [+] E'; h2 := h3 [+] E [+] A'; -- * h3 := h4 [+] A [+] B'; h4 := h0 [+] B [+] C'; h0 := T; -- * } -- */ -- --/* Some examples: -- * "" 9c1185a5c5e9fc54612808977ee8f548b2258d31 -- * "a" 0bdc9d2d256b3ee9daae347be6f4dc835a467ffe -- * "abc" 8eb208f7e05d987a9b044a8e98c6b087f15a0bfc -- * "message digest" 5d0689ef49d2fae572b881b123a85ffa21595f36 -- * "a...z" f71c27109c692c1b56bbdceb5b9d2865b3708dbc -- * "abcdbcde...nopq" 12a053384a9c0c88e405a06c27dcf49ada62eb2b -- * "A...Za...z0...9" b0e20b6e3116640286ed3a87a5713079b21f5189 -- * 8 times "1234567890" 9b752e45573d4b39f4dbd3323cab82bf63326bfb -- * 1 million times "a" 52783243c1697bdbe16d37f97f68f08325dc1528 -- */ -- --static void --burn_stack (int bytes) --{ -- char buf[150]; -- -- memset (buf, 0, sizeof buf); -- bytes -= sizeof buf; -- if (bytes > 0) -- burn_stack (bytes); --} -- -- -- --void --rmd160_init( RMD160_CONTEXT *hd ) --{ -- hd->h0 = 0x67452301; -- hd->h1 = 0xEFCDAB89; -- hd->h2 = 0x98BADCFE; -- hd->h3 = 0x10325476; -- hd->h4 = 0xC3D2E1F0; -- hd->nblocks = 0; -- hd->count = 0; --} -- -- -- --/**************** -- * Transform the message X which consists of 16 32-bit-words -- */ --static void --transform( RMD160_CONTEXT *hd, byte *data ) --{ -- u32 a,b,c,d,e,aa,bb,cc,dd,ee,t; -- #ifdef BIG_ENDIAN_HOST -- u32 x[16]; -- { int i; -- byte *p2, *p1; -- for(i=0, p1=data, p2=(byte*)x; i < 16; i++, p2 += 4 ) { -- p2[3] = *p1++; -- p2[2] = *p1++; -- p2[1] = *p1++; -- p2[0] = *p1++; -- } -- } -- #else -- #if 0 -- u32 *x =(u32*)data; -- #else -- /* this version is better because it is always aligned; -- * The performance penalty on a 586-100 is about 6% which -- * is acceptable - because the data is more local it might -- * also be possible that this is faster on some machines. -- * This function (when compiled with -02 on gcc 2.7.2) -- * executes on a 586-100 (39.73 bogomips) at about 1900kb/sec; -- * [measured with a 4MB data and "gpgm --print-md rmd160"] */ -- u32 x[16]; -- memcpy( x, data, 64 ); -- #endif -- #endif -- -- --#define K0 0x00000000 --#define K1 0x5A827999 --#define K2 0x6ED9EBA1 --#define K3 0x8F1BBCDC --#define K4 0xA953FD4E --#define KK0 0x50A28BE6 --#define KK1 0x5C4DD124 --#define KK2 0x6D703EF3 --#define KK3 0x7A6D76E9 --#define KK4 0x00000000 --#define F0(x,y,z) ( (x) ^ (y) ^ (z) ) --#define F1(x,y,z) ( ((x) & (y)) | (~(x) & (z)) ) --#define F2(x,y,z) ( ((x) | ~(y)) ^ (z) ) --#define F3(x,y,z) ( ((x) & (z)) | ((y) & ~(z)) ) --#define F4(x,y,z) ( (x) ^ ((y) | ~(z)) ) --#define R(a,b,c,d,e,f,k,r,s) do { t = a + f(b,c,d) + k + x[r]; \ -- a = rol(t,s) + e; \ -- c = rol(c,10); \ -- } while(0) -- -- /* left lane */ -- a = hd->h0; -- b = hd->h1; -- c = hd->h2; -- d = hd->h3; -- e = hd->h4; -- R( a, b, c, d, e, F0, K0, 0, 11 ); -- R( e, a, b, c, d, F0, K0, 1, 14 ); -- R( d, e, a, b, c, F0, K0, 2, 15 ); -- R( c, d, e, a, b, F0, K0, 3, 12 ); -- R( b, c, d, e, a, F0, K0, 4, 5 ); -- R( a, b, c, d, e, F0, K0, 5, 8 ); -- R( e, a, b, c, d, F0, K0, 6, 7 ); -- R( d, e, a, b, c, F0, K0, 7, 9 ); -- R( c, d, e, a, b, F0, K0, 8, 11 ); -- R( b, c, d, e, a, F0, K0, 9, 13 ); -- R( a, b, c, d, e, F0, K0, 10, 14 ); -- R( e, a, b, c, d, F0, K0, 11, 15 ); -- R( d, e, a, b, c, F0, K0, 12, 6 ); -- R( c, d, e, a, b, F0, K0, 13, 7 ); -- R( b, c, d, e, a, F0, K0, 14, 9 ); -- R( a, b, c, d, e, F0, K0, 15, 8 ); -- R( e, a, b, c, d, F1, K1, 7, 7 ); -- R( d, e, a, b, c, F1, K1, 4, 6 ); -- R( c, d, e, a, b, F1, K1, 13, 8 ); -- R( b, c, d, e, a, F1, K1, 1, 13 ); -- R( a, b, c, d, e, F1, K1, 10, 11 ); -- R( e, a, b, c, d, F1, K1, 6, 9 ); -- R( d, e, a, b, c, F1, K1, 15, 7 ); -- R( c, d, e, a, b, F1, K1, 3, 15 ); -- R( b, c, d, e, a, F1, K1, 12, 7 ); -- R( a, b, c, d, e, F1, K1, 0, 12 ); -- R( e, a, b, c, d, F1, K1, 9, 15 ); -- R( d, e, a, b, c, F1, K1, 5, 9 ); -- R( c, d, e, a, b, F1, K1, 2, 11 ); -- R( b, c, d, e, a, F1, K1, 14, 7 ); -- R( a, b, c, d, e, F1, K1, 11, 13 ); -- R( e, a, b, c, d, F1, K1, 8, 12 ); -- R( d, e, a, b, c, F2, K2, 3, 11 ); -- R( c, d, e, a, b, F2, K2, 10, 13 ); -- R( b, c, d, e, a, F2, K2, 14, 6 ); -- R( a, b, c, d, e, F2, K2, 4, 7 ); -- R( e, a, b, c, d, F2, K2, 9, 14 ); -- R( d, e, a, b, c, F2, K2, 15, 9 ); -- R( c, d, e, a, b, F2, K2, 8, 13 ); -- R( b, c, d, e, a, F2, K2, 1, 15 ); -- R( a, b, c, d, e, F2, K2, 2, 14 ); -- R( e, a, b, c, d, F2, K2, 7, 8 ); -- R( d, e, a, b, c, F2, K2, 0, 13 ); -- R( c, d, e, a, b, F2, K2, 6, 6 ); -- R( b, c, d, e, a, F2, K2, 13, 5 ); -- R( a, b, c, d, e, F2, K2, 11, 12 ); -- R( e, a, b, c, d, F2, K2, 5, 7 ); -- R( d, e, a, b, c, F2, K2, 12, 5 ); -- R( c, d, e, a, b, F3, K3, 1, 11 ); -- R( b, c, d, e, a, F3, K3, 9, 12 ); -- R( a, b, c, d, e, F3, K3, 11, 14 ); -- R( e, a, b, c, d, F3, K3, 10, 15 ); -- R( d, e, a, b, c, F3, K3, 0, 14 ); -- R( c, d, e, a, b, F3, K3, 8, 15 ); -- R( b, c, d, e, a, F3, K3, 12, 9 ); -- R( a, b, c, d, e, F3, K3, 4, 8 ); -- R( e, a, b, c, d, F3, K3, 13, 9 ); -- R( d, e, a, b, c, F3, K3, 3, 14 ); -- R( c, d, e, a, b, F3, K3, 7, 5 ); -- R( b, c, d, e, a, F3, K3, 15, 6 ); -- R( a, b, c, d, e, F3, K3, 14, 8 ); -- R( e, a, b, c, d, F3, K3, 5, 6 ); -- R( d, e, a, b, c, F3, K3, 6, 5 ); -- R( c, d, e, a, b, F3, K3, 2, 12 ); -- R( b, c, d, e, a, F4, K4, 4, 9 ); -- R( a, b, c, d, e, F4, K4, 0, 15 ); -- R( e, a, b, c, d, F4, K4, 5, 5 ); -- R( d, e, a, b, c, F4, K4, 9, 11 ); -- R( c, d, e, a, b, F4, K4, 7, 6 ); -- R( b, c, d, e, a, F4, K4, 12, 8 ); -- R( a, b, c, d, e, F4, K4, 2, 13 ); -- R( e, a, b, c, d, F4, K4, 10, 12 ); -- R( d, e, a, b, c, F4, K4, 14, 5 ); -- R( c, d, e, a, b, F4, K4, 1, 12 ); -- R( b, c, d, e, a, F4, K4, 3, 13 ); -- R( a, b, c, d, e, F4, K4, 8, 14 ); -- R( e, a, b, c, d, F4, K4, 11, 11 ); -- R( d, e, a, b, c, F4, K4, 6, 8 ); -- R( c, d, e, a, b, F4, K4, 15, 5 ); -- R( b, c, d, e, a, F4, K4, 13, 6 ); -- -- aa = a; bb = b; cc = c; dd = d; ee = e; -- -- /* right lane */ -- a = hd->h0; -- b = hd->h1; -- c = hd->h2; -- d = hd->h3; -- e = hd->h4; -- R( a, b, c, d, e, F4, KK0, 5, 8); -- R( e, a, b, c, d, F4, KK0, 14, 9); -- R( d, e, a, b, c, F4, KK0, 7, 9); -- R( c, d, e, a, b, F4, KK0, 0, 11); -- R( b, c, d, e, a, F4, KK0, 9, 13); -- R( a, b, c, d, e, F4, KK0, 2, 15); -- R( e, a, b, c, d, F4, KK0, 11, 15); -- R( d, e, a, b, c, F4, KK0, 4, 5); -- R( c, d, e, a, b, F4, KK0, 13, 7); -- R( b, c, d, e, a, F4, KK0, 6, 7); -- R( a, b, c, d, e, F4, KK0, 15, 8); -- R( e, a, b, c, d, F4, KK0, 8, 11); -- R( d, e, a, b, c, F4, KK0, 1, 14); -- R( c, d, e, a, b, F4, KK0, 10, 14); -- R( b, c, d, e, a, F4, KK0, 3, 12); -- R( a, b, c, d, e, F4, KK0, 12, 6); -- R( e, a, b, c, d, F3, KK1, 6, 9); -- R( d, e, a, b, c, F3, KK1, 11, 13); -- R( c, d, e, a, b, F3, KK1, 3, 15); -- R( b, c, d, e, a, F3, KK1, 7, 7); -- R( a, b, c, d, e, F3, KK1, 0, 12); -- R( e, a, b, c, d, F3, KK1, 13, 8); -- R( d, e, a, b, c, F3, KK1, 5, 9); -- R( c, d, e, a, b, F3, KK1, 10, 11); -- R( b, c, d, e, a, F3, KK1, 14, 7); -- R( a, b, c, d, e, F3, KK1, 15, 7); -- R( e, a, b, c, d, F3, KK1, 8, 12); -- R( d, e, a, b, c, F3, KK1, 12, 7); -- R( c, d, e, a, b, F3, KK1, 4, 6); -- R( b, c, d, e, a, F3, KK1, 9, 15); -- R( a, b, c, d, e, F3, KK1, 1, 13); -- R( e, a, b, c, d, F3, KK1, 2, 11); -- R( d, e, a, b, c, F2, KK2, 15, 9); -- R( c, d, e, a, b, F2, KK2, 5, 7); -- R( b, c, d, e, a, F2, KK2, 1, 15); -- R( a, b, c, d, e, F2, KK2, 3, 11); -- R( e, a, b, c, d, F2, KK2, 7, 8); -- R( d, e, a, b, c, F2, KK2, 14, 6); -- R( c, d, e, a, b, F2, KK2, 6, 6); -- R( b, c, d, e, a, F2, KK2, 9, 14); -- R( a, b, c, d, e, F2, KK2, 11, 12); -- R( e, a, b, c, d, F2, KK2, 8, 13); -- R( d, e, a, b, c, F2, KK2, 12, 5); -- R( c, d, e, a, b, F2, KK2, 2, 14); -- R( b, c, d, e, a, F2, KK2, 10, 13); -- R( a, b, c, d, e, F2, KK2, 0, 13); -- R( e, a, b, c, d, F2, KK2, 4, 7); -- R( d, e, a, b, c, F2, KK2, 13, 5); -- R( c, d, e, a, b, F1, KK3, 8, 15); -- R( b, c, d, e, a, F1, KK3, 6, 5); -- R( a, b, c, d, e, F1, KK3, 4, 8); -- R( e, a, b, c, d, F1, KK3, 1, 11); -- R( d, e, a, b, c, F1, KK3, 3, 14); -- R( c, d, e, a, b, F1, KK3, 11, 14); -- R( b, c, d, e, a, F1, KK3, 15, 6); -- R( a, b, c, d, e, F1, KK3, 0, 14); -- R( e, a, b, c, d, F1, KK3, 5, 6); -- R( d, e, a, b, c, F1, KK3, 12, 9); -- R( c, d, e, a, b, F1, KK3, 2, 12); -- R( b, c, d, e, a, F1, KK3, 13, 9); -- R( a, b, c, d, e, F1, KK3, 9, 12); -- R( e, a, b, c, d, F1, KK3, 7, 5); -- R( d, e, a, b, c, F1, KK3, 10, 15); -- R( c, d, e, a, b, F1, KK3, 14, 8); -- R( b, c, d, e, a, F0, KK4, 12, 8); -- R( a, b, c, d, e, F0, KK4, 15, 5); -- R( e, a, b, c, d, F0, KK4, 10, 12); -- R( d, e, a, b, c, F0, KK4, 4, 9); -- R( c, d, e, a, b, F0, KK4, 1, 12); -- R( b, c, d, e, a, F0, KK4, 5, 5); -- R( a, b, c, d, e, F0, KK4, 8, 14); -- R( e, a, b, c, d, F0, KK4, 7, 6); -- R( d, e, a, b, c, F0, KK4, 6, 8); -- R( c, d, e, a, b, F0, KK4, 2, 13); -- R( b, c, d, e, a, F0, KK4, 13, 6); -- R( a, b, c, d, e, F0, KK4, 14, 5); -- R( e, a, b, c, d, F0, KK4, 0, 15); -- R( d, e, a, b, c, F0, KK4, 3, 13); -- R( c, d, e, a, b, F0, KK4, 9, 11); -- R( b, c, d, e, a, F0, KK4, 11, 11); -- -- -- t = hd->h1 + d + cc; -- hd->h1 = hd->h2 + e + dd; -- hd->h2 = hd->h3 + a + ee; -- hd->h3 = hd->h4 + b + aa; -- hd->h4 = hd->h0 + c + bb; -- hd->h0 = t; --} -- -- --/* Update the message digest with the contents -- * of INBUF with length INLEN. -- */ --static void --rmd160_write( RMD160_CONTEXT *hd, byte *inbuf, size_t inlen) --{ -- if( hd->count == 64 ) { /* flush the buffer */ -- transform( hd, hd->buf ); -- burn_stack (108+5*sizeof(void*)); -- hd->count = 0; -- hd->nblocks++; -- } -- if( !inbuf ) -- return; -- if( hd->count ) { -- for( ; inlen && hd->count < 64; inlen-- ) -- hd->buf[hd->count++] = *inbuf++; -- rmd160_write( hd, NULL, 0 ); -- if( !inlen ) -- return; -- } -- -- while( inlen >= 64 ) { -- transform( hd, inbuf ); -- hd->count = 0; -- hd->nblocks++; -- inlen -= 64; -- inbuf += 64; -- } -- burn_stack (108+5*sizeof(void*)); -- for( ; inlen && hd->count < 64; inlen-- ) -- hd->buf[hd->count++] = *inbuf++; --} -- --/**************** -- * Apply the rmd160 transform function on the buffer which must have -- * a length 64 bytes. Do not use this function together with the -- * other functions, use rmd160_init to initialize internal variables. -- * Returns: 16 bytes in buffer with the mixed contentes of buffer. -- */ --void --rmd160_mixblock( RMD160_CONTEXT *hd, char *buffer ) --{ -- char *p = buffer; -- transform( hd, buffer ); -- #define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0) -- X(0); -- X(1); -- X(2); -- X(3); -- X(4); -- #undef X --} -- -- --/* The routine terminates the computation -- */ -- --static void --rmd160_final( RMD160_CONTEXT *hd ) --{ -- u32 t, msb, lsb; -- byte *p; -- -- rmd160_write(hd, NULL, 0); /* flush */; -- -- t = hd->nblocks; -- /* multiply by 64 to make a byte count */ -- lsb = t << 6; -- msb = t >> 26; -- /* add the count */ -- t = lsb; -- if( (lsb += hd->count) < t ) -- msb++; -- /* multiply by 8 to make a bit count */ -- t = lsb; -- lsb <<= 3; -- msb <<= 3; -- msb |= t >> 29; -- -- if( hd->count < 56 ) { /* enough room */ -- hd->buf[hd->count++] = 0x80; /* pad */ -- while( hd->count < 56 ) -- hd->buf[hd->count++] = 0; /* pad */ -- } -- else { /* need one extra block */ -- hd->buf[hd->count++] = 0x80; /* pad character */ -- while( hd->count < 64 ) -- hd->buf[hd->count++] = 0; -- rmd160_write(hd, NULL, 0); /* flush */; -- memset(hd->buf, 0, 56 ); /* fill next block with zeroes */ -- } -- /* append the 64 bit count */ -- hd->buf[56] = lsb ; -- hd->buf[57] = lsb >> 8; -- hd->buf[58] = lsb >> 16; -- hd->buf[59] = lsb >> 24; -- hd->buf[60] = msb ; -- hd->buf[61] = msb >> 8; -- hd->buf[62] = msb >> 16; -- hd->buf[63] = msb >> 24; -- transform( hd, hd->buf ); -- burn_stack (108+5*sizeof(void*)); -- -- p = hd->buf; -- #ifdef BIG_ENDIAN_HOST -- #define X(a) do { *p++ = hd->h##a ; *p++ = hd->h##a >> 8; \ -- *p++ = hd->h##a >> 16; *p++ = hd->h##a >> 24; } while(0) -- #else /* little endian */ -- #define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0) -- #endif -- X(0); -- X(1); -- X(2); -- X(3); -- X(4); -- #undef X --} -- --static byte * --rmd160_read( RMD160_CONTEXT *hd ) --{ -- return hd->buf; --} -- -- -- --/**************** -- * Shortcut functions which puts the hash value of the supplied buffer -- * into outbuf which must have a size of 20 bytes. -- */ --void --rmd160_hash_buffer( char *outbuf, const char *buffer, size_t length ) --{ -- RMD160_CONTEXT hd; -- -- rmd160_init( &hd ); -- rmd160_write( &hd, (byte*)buffer, length ); -- rmd160_final( &hd ); -- memcpy( outbuf, hd.buf, 20 ); --} -- -- --/**************** -- * Return some information about the algorithm. We need algo here to -- * distinguish different flavors of the algorithm. -- * Returns: A pointer to string describing the algorithm or NULL if -- * the ALGO is invalid. -- */ --static const char * --rmd160_get_info( int algo, size_t *contextsize, -- byte **r_asnoid, int *r_asnlen, int *r_mdlen, -- void (**r_init)( void *c ), -- void (**r_write)( void *c, byte *buf, size_t nbytes ), -- void (**r_final)( void *c ), -- byte *(**r_read)( void *c ) -- ) --{ -- static byte asn[15] = /* Object ID is 1.3.36.3.2.1 */ -- { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03, -- 0x02, 0x01, 0x05, 0x00, 0x04, 0x14 }; -- -- if( algo != 3 ) -- return NULL; -- -- *contextsize = sizeof(RMD160_CONTEXT); -- *r_asnoid = asn; -- *r_asnlen = DIM(asn); -- *r_mdlen = 20; -- *(void (**)(RMD160_CONTEXT *))r_init = rmd160_init; -- *(void (**)(RMD160_CONTEXT *, byte*, size_t))r_write = rmd160_write; -- *(void (**)(RMD160_CONTEXT *))r_final = rmd160_final; -- *(byte *(**)(RMD160_CONTEXT *))r_read = rmd160_read; -- -- return "RIPEMD160"; --} -- -- --#ifndef IS_MODULE --static --#endif --const char * const gnupgext_version = "RMD160 ($Revision: 1.17.2.4 $)"; -- --static struct { -- int class; -- int version; -- int value; -- void (*func)(void); --} func_table[] = { -- { 10, 1, 0, (void(*)(void))rmd160_get_info }, -- { 11, 1, 3 }, --}; -- -- --#ifndef IS_MODULE --static --#endif --void * --gnupgext_enum_func( int what, int *sequence, int *class, int *vers ) --{ -- void *ret; -- int i = *sequence; -- -- do { -- if( i >= DIM(func_table) || i < 0 ) { -- return NULL; -- } -- *class = func_table[i].class; -- *vers = func_table[i].version; -- switch( *class ) { -- case 11: -- case 21: -- case 31: -- ret = &func_table[i].value; -- break; -- default: -- ret = func_table[i].func; -- break; -- } -- i++; -- } while( what && what != *class ); -- -- *sequence = i; -- return ret; --} -- -- -- --#ifndef __HURD__ --#ifndef IS_MODULE --void --rmd160_constructor(void) --{ -- register_internal_cipher_extension( gnupgext_version, gnupgext_enum_func ); --} --#endif --#endif -diff --git a/random/random.c b/random/random.c -deleted file mode 100644 -index 8f76c5b..0000000 ---- a/random/random.c -+++ /dev/null -@@ -1,650 +0,0 @@ --/* random.c - A single-file translator providing random data -- Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc. -- -- 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, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -- --#define _GNU_SOURCE 1 -- --#include <hurd/paths.h> --#include <hurd/trivfs.h> --#include <hurd/startup.h> --#include <stdio.h> --#include <stdlib.h> --#include <argp.h> --#include <argz.h> --#include <error.h> --#include <string.h> --#include <fcntl.h> --#include <sys/mman.h> --#include <pthread.h> --#include <assert.h> -- --#include <version.h> -- --#include "random.h" --#include "gnupg-random.h" -- --/* Our control port. */ --struct trivfs_control *fsys; -- --int read_blocked; /* For read and select. */ --pthread_cond_t wait; /* For read and select. */ --pthread_cond_t select_alert; /* For read and select. */ -- -- --/* The quality of randomness we provide. -- 0: Very weak randomness based on time() and getrusage(). -- No external random data is used. -- 1: Pseudo random numbers based on all available real random -- numbers. -- 2: Strong random numbers with a somewhat guaranteed entropy. --*/ --#define DEFAULT_LEVEL 2 --static int level = DEFAULT_LEVEL; -- --/* Name of file to use as seed. */ --static char *seed_file; -- --/* The random bytes we collected. */ --char gatherbuf[GATHERBUFSIZE]; -- --/* The current positions in gatherbuf[]. */ --int gatherrpos; --int gatherwpos; -- --/* XXX Yuk Yuk. */ --#define POOLSIZE 600 -- --/* Take up to length bytes from gather_random if available. If -- nothing is available, sleep until something becomes available. -- Must be called with global_lock held. */ --int --gather_random( void (*add)(const void*, size_t, int), int requester, -- size_t length, int level ) --{ -- int avail = (gatherwpos - gatherrpos + GATHERBUFSIZE) % GATHERBUFSIZE; -- int first = GATHERBUFSIZE - gatherrpos; -- int second = length - first; -- -- /* If level is zero, we should not block and not add anything -- to the pool. */ -- if( !level ) -- return 0; -- -- /* io_read() should guarantee that there is always data available. */ -- if (level == 2) -- assert (avail); -- -- if (length > avail) -- length = avail; -- -- if (first > length) -- first = length; -- (*add) (&gatherbuf[gatherrpos], first, requester); -- gatherrpos = (gatherrpos + first) % GATHERBUFSIZE; -- if (second > 0) -- { -- (*add) (&gatherbuf[gatherrpos], second, requester); -- gatherrpos += second; -- } -- return length; --} -- -- --const char *argp_program_version = STANDARD_HURD_VERSION (random); -- --/* This lock protects the GnuPG code. */ --static pthread_mutex_t global_lock; -- --/* Trivfs hooks. */ --int trivfs_fstype = FSTYPE_MISC; --int trivfs_fsid = 0; -- --int trivfs_allow_open = O_READ | O_WRITE; -- --int trivfs_support_read = 1; --int trivfs_support_write = 1; --int trivfs_support_exec = 0; -- --void --trivfs_modify_stat (struct trivfs_protid *cred, struct stat *st) --{ -- /* Mark the node as a read-only plain file. */ -- st->st_mode &= ~S_IFMT; -- st->st_mode |= (S_IFCHR); -- st->st_size = 0; --} -- --error_t --trivfs_goaway (struct trivfs_control *cntl, int flags) --{ -- update_random_seed_file (); -- exit (0); --} -- --/* Read data from an IO object. If offset is -1, read from the object -- maintained file pointer. If the object is not seekable, offset is -- ignored. The amount desired to be read is in AMOUNT. */ --error_t --trivfs_S_io_read (struct trivfs_protid *cred, -- mach_port_t reply, mach_msg_type_name_t reply_type, -- data_t *data, mach_msg_type_number_t *data_len, -- loff_t offs, mach_msg_type_number_t amount) --{ -- error_t err; -- mach_msg_type_number_t read_amount = 0; -- void *buf = NULL; -- size_t length; -- -- /* Deny access if they have bad credentials. */ -- if (! cred) -- return EOPNOTSUPP; -- else if (! (cred->po->openmodes & O_READ)) -- return EBADF; -- -- pthread_mutex_lock (&global_lock); -- -- while (amount > 0) -- { -- mach_msg_type_number_t new_amount; -- /* XXX: It would be nice to fix readable_pool to work for sizes -- greater than the POOLSIZE. Otherwise we risk detecting too -- late that we run out of entropy and all that entropy is -- wasted. */ -- while (readable_pool (amount, level) == 0) -- { -- if (cred->po->openmodes & O_NONBLOCK) -- { -- pthread_mutex_unlock (&global_lock); -- err = EWOULDBLOCK; -- goto errout; -- } -- read_blocked = 1; -- if (pthread_hurd_cond_wait_np (&wait, &global_lock)) -- { -- pthread_mutex_unlock (&global_lock); -- err = EINTR; -- goto errout; -- } -- /* See term/users.c for possible race? */ -- } -- -- /* Possibly allocate a new buffer. */ -- if (*data_len < amount) -- { -- *data = mmap (0, amount, PROT_READ|PROT_WRITE, -- MAP_ANON, 0, 0); -- -- if (*data == MAP_FAILED) -- { -- pthread_mutex_unlock (&global_lock); -- return errno; -- } -- -- /* Keep track of our map in case of errors. */ -- buf = *data, length = amount; -- -- /* Update DATA_LEN to reflect the new buffers size. */ -- *data_len = amount; -- } -- -- new_amount = read_pool (((byte *) *data) + read_amount, amount, level); -- read_amount += new_amount; -- amount -= new_amount; -- } -- -- /* Set atime, see term/users.c */ -- -- pthread_mutex_unlock (&global_lock); -- *data_len = read_amount; -- return 0; -- -- errout: -- if (buf) -- munmap (buf, length); -- return err; --} -- --/* Write data to an IO object. If offset is -1, write at the object -- maintained file pointer. If the object is not seekable, offset is -- ignored. The amount successfully written is returned in amount. A -- given user should not have more than one outstanding io_write on an -- object at a time; servers implement congestion control by delaying -- responses to io_write. Servers may drop data (returning ENOBUFS) -- if they receive more than one write when not prepared for it. */ --error_t --trivfs_S_io_write (struct trivfs_protid *cred, -- mach_port_t reply, -- mach_msg_type_name_t replytype, -- data_t data, -- mach_msg_type_number_t datalen, -- loff_t offset, -- mach_msg_type_number_t *amount) --{ -- int i = 0; -- /* Deny access if they have bad credentials. */ -- if (! cred) -- return EOPNOTSUPP; -- else if (! (cred->po->openmodes & O_WRITE)) -- return EBADF; -- -- pthread_mutex_lock (&global_lock); -- -- while (i < datalen) -- { -- gatherbuf[gatherwpos] = data[i++]; -- gatherwpos = (gatherwpos + 1) % GATHERBUFSIZE; -- if (gatherrpos == gatherwpos) -- /* Overrun. */ -- gatherrpos = (gatherrpos + 1) % GATHERBUFSIZE; -- } -- *amount = datalen; -- -- if (datalen > 0 && read_blocked) -- { -- read_blocked = 0; -- pthread_cond_broadcast (&wait); -- pthread_cond_broadcast (&select_alert); -- } -- -- pthread_mutex_unlock (&global_lock); -- return 0; --} -- --/* Tell how much data can be read from the object without blocking for -- a "long time" (this should be the same meaning of "long time" used -- by the nonblocking flag. */ --kern_return_t --trivfs_S_io_readable (struct trivfs_protid *cred, -- mach_port_t reply, mach_msg_type_name_t replytype, -- mach_msg_type_number_t *amount) --{ -- /* Deny access if they have bad credentials. */ -- if (! cred) -- return EOPNOTSUPP; -- else if (! (cred->po->openmodes & O_READ)) -- return EBADF; -- -- pthread_mutex_lock (&global_lock); -- -- /* XXX: Before initialization, the amount depends on the amount we -- want to read. Assume some medium value. */ -- *amount = readable_pool (POOLSIZE/2, level); -- -- pthread_mutex_unlock (&global_lock); -- -- return 0; --} -- --/* SELECT_TYPE is the bitwise OR of SELECT_READ, SELECT_WRITE, and SELECT_URG. -- Block until one of the indicated types of i/o can be done "quickly", and -- return the types that are then available. ID_TAG is returned as passed; it -- is just for the convenience of the user in matching up reply messages with -- specific requests sent. */ --error_t --trivfs_S_io_select (struct trivfs_protid *cred, -- mach_port_t reply, -- mach_msg_type_name_t reply_type, -- int *type) --{ -- if (!cred) -- return EOPNOTSUPP; -- -- /* We only deal with SELECT_READ and SELECT_WRITE here. */ -- if (*type & ~(SELECT_READ | SELECT_WRITE)) -- return EINVAL; -- -- if (*type == 0) -- return 0; -- -- pthread_mutex_lock (&global_lock); -- -- while (1) -- { -- /* XXX Before initialization, readable_pool depends on length. */ -- int avail = readable_pool (POOLSIZE/2, level); -- -- if (avail != 0 || *type & SELECT_WRITE) -- { -- *type = (avail ? SELECT_READ : 0) | (*type & SELECT_WRITE); -- pthread_mutex_unlock (&global_lock); -- return 0; -- } -- -- ports_interrupt_self_on_port_death (cred, reply); -- read_blocked = 1; -- -- if (pthread_hurd_cond_wait_np (&select_alert, &global_lock)) -- { -- *type = 0; -- pthread_mutex_unlock (&global_lock); -- return EINTR; -- } -- } --} -- -- --/* Change current read/write offset */ --error_t --trivfs_S_io_seek (struct trivfs_protid *cred, -- mach_port_t reply, mach_msg_type_name_t reply_type, -- loff_t offs, int whence, loff_t *new_offs) --{ -- if (! cred) -- return EOPNOTSUPP; -- -- /* Not seekable. */ -- return ESPIPE; --} -- --/* Change the size of the file. If the size increases, new blocks are -- zero-filled. After successful return, it is safe to reference mapped -- areas of the file up to NEW_SIZE. */ --error_t --trivfs_S_file_set_size (struct trivfs_protid *cred, -- mach_port_t reply, mach_msg_type_name_t reply_type, -- loff_t size) --{ -- if (!cred) -- return EOPNOTSUPP; -- -- return size == 0 ? 0 : EINVAL; --} -- --/* These four routines modify the O_APPEND, O_ASYNC, O_FSYNC, and -- O_NONBLOCK bits for the IO object. In addition, io_get_openmodes -- will tell you which of O_READ, O_WRITE, and O_EXEC the object can -- be used for. The O_ASYNC bit affects icky async I/O; good async -- I/O is done through io_async which is orthogonal to these calls. */ --error_t --trivfs_S_io_set_all_openmodes(struct trivfs_protid *cred, -- mach_port_t reply, -- mach_msg_type_name_t reply_type, -- int mode) --{ -- if (!cred) -- return EOPNOTSUPP; -- -- return 0; --} -- --error_t --trivfs_S_io_set_some_openmodes (struct trivfs_protid *cred, -- mach_port_t reply, -- mach_msg_type_name_t reply_type, -- int bits) --{ -- if (!cred) -- return EOPNOTSUPP; -- -- return 0; --} -- --error_t --trivfs_S_io_get_owner (struct trivfs_protid *cred, -- mach_port_t reply, -- mach_msg_type_name_t reply_type, -- pid_t *owner) --{ -- if (!cred) -- return EOPNOTSUPP; -- -- *owner = 0; -- return 0; --} -- --error_t --trivfs_S_io_mod_owner (struct trivfs_protid *cred, -- mach_port_t reply, mach_msg_type_name_t reply_type, -- pid_t owner) --{ -- if (!cred) -- return EOPNOTSUPP; -- -- return EINVAL; --} -- --/* Return objects mapping the data underlying this memory object. If -- the object can be read then memobjrd will be provided; if the -- object can be written then memobjwr will be provided. For objects -- where read data and write data are the same, these objects will be -- equal, otherwise they will be disjoint. Servers are permitted to -- implement io_map but not io_map_cntl. Some objects do not provide -- mapping; they will set none of the ports and return an error. Such -- objects can still be accessed by io_read and io_write. */ --error_t --trivfs_S_io_map(struct trivfs_protid *cred, -- mach_port_t reply, mach_msg_type_name_t reply_type, -- mach_port_t *rdobj, -- mach_msg_type_name_t *rdtype, -- mach_port_t *wrobj, -- mach_msg_type_name_t *wrtype) --{ -- if (!cred) -- return EOPNOTSUPP; -- -- return EINVAL; --} -- -- --int --random_demuxer (mach_msg_header_t *inp, -- mach_msg_header_t *outp) --{ -- extern int startup_notify_server (mach_msg_header_t *, mach_msg_header_t *); -- -- return (trivfs_demuxer (inp, outp) -- || startup_notify_server (inp, outp)); --} -- -- --/* Options processing. We accept the same options on the command line -- and from fsys_set_options. */ -- --static const struct argp_option options[] = --{ -- {"weak", 'w', 0, 0, "Output weak pseudo random data"}, -- {"fast", 'f', 0, 0, "Output cheap random data fast"}, -- {"secure", 's', 0, 0, "Output cryptographically secure random"}, -- {"seed-file", 'S', "FILE", 0, "Use FILE to remember the seed"}, -- {0} --}; -- --static error_t --parse_opt (int opt, char *arg, struct argp_state *state) --{ -- switch (opt) -- { -- default: -- return ARGP_ERR_UNKNOWN; -- case ARGP_KEY_INIT: -- case ARGP_KEY_SUCCESS: -- case ARGP_KEY_ERROR: -- break; -- -- case 'w': -- { -- level = 0; -- break; -- } -- case 'f': -- { -- level = 1; -- break; -- } -- case 's': -- { -- level = 2; -- break; -- } -- case 'S': -- { -- seed_file = strdup (arg); -- set_random_seed_file (arg); -- } -- } -- return 0; --} -- --/* This will be called from libtrivfs to help construct the answer -- to an fsys_get_options RPC. */ --error_t --trivfs_append_args (struct trivfs_control *fsys, -- char **argz, size_t *argz_len) --{ -- error_t err = 0; -- char *opt; -- -- pthread_mutex_lock (&global_lock); -- switch (level) -- { -- case 0: -- opt = "--weak"; -- break; -- -- case 1: -- opt = "--fast"; -- break; -- -- default: -- opt = "--secure"; -- } -- if (level != DEFAULT_LEVEL) -- err = argz_add (argz, argz_len, opt); -- -- if (!err && seed_file) -- { -- if (asprintf (&opt, "--seed-file=%s", seed_file) < 0) -- err = ENOMEM; -- else -- { -- err = argz_add (argz, argz_len, opt); -- free (opt); -- } -- } -- pthread_mutex_unlock (&global_lock); -- -- return err; --} -- --static struct argp random_argp = --{ options, parse_opt, 0, -- "A translator providing random output." }; -- --/* Setting this variable makes libtrivfs use our argp to -- parse options passed in an fsys_set_options RPC. */ --struct argp *trivfs_runtime_argp = &random_argp; -- --struct port_class *shutdown_notify_class; -- --/* The system is going down; destroy all the extant port rights. That -- will cause net channels and such to close promptly. */ --error_t --S_startup_dosync (mach_port_t handle) --{ -- struct port_info *inpi = ports_lookup_port (fsys->pi.bucket, handle, -- shutdown_notify_class); -- -- if (!inpi) -- return EOPNOTSUPP; -- -- update_random_seed_file (); -- return 0; --} -- --void --sigterm_handler (int signo) --{ -- update_random_seed_file (); -- signal (SIGTERM, SIG_DFL); -- raise (SIGTERM); --} -- --static error_t --arrange_shutdown_notification () --{ -- error_t err; -- mach_port_t initport, notify; -- struct port_info *pi; -- -- shutdown_notify_class = ports_create_class (0, 0); -- -- signal (SIGTERM, sigterm_handler); -- -- /* Arrange to get notified when the system goes down, -- but if we fail for some reason, just silently give up. No big deal. */ -- -- err = ports_create_port (shutdown_notify_class, fsys->pi.bucket, -- sizeof (struct port_info), &pi); -- if (err) -- return err; -- -- initport = file_name_lookup (_SERVERS_STARTUP, 0, 0); -- if (! MACH_PORT_VALID (initport)) -- return errno; -- -- notify = ports_get_send_right (pi); -- ports_port_deref (pi); -- err = startup_request_notification (initport, notify, -- MACH_MSG_TYPE_MAKE_SEND, -- program_invocation_short_name); -- -- mach_port_deallocate (mach_task_self (), notify); -- mach_port_deallocate (mach_task_self (), initport); -- return err; --} -- -- --int --main (int argc, char **argv) --{ -- error_t err; -- mach_port_t bootstrap; -- -- /* Initialize the lock that will protect everything. -- We must do this before argp_parse, because parse_opt (above) will -- use the lock. */ -- pthread_mutex_init (&global_lock, NULL); -- -- /* The conditions are used to implement proper read/select -- behaviour. */ -- pthread_cond_init (&wait, NULL); -- pthread_cond_init (&select_alert, NULL); -- -- /* We use the same argp for options available at startup -- as for options we'll accept in an fsys_set_options RPC. */ -- argp_parse (&random_argp, argc, argv, 0, 0, 0); -- -- task_get_bootstrap_port (mach_task_self (), &bootstrap); -- if (bootstrap == MACH_PORT_NULL) -- error (1, 0, "Must be started as a translator"); -- -- /* Reply to our parent */ -- err = trivfs_startup (bootstrap, 0, 0, 0, 0, 0, &fsys); -- mach_port_deallocate (mach_task_self (), bootstrap); -- if (err) -- error (3, err, "trivfs_startup"); -- -- err = arrange_shutdown_notification (); -- if (err) -- error (0, err, "Cannot request shutdown notification"); -- -- /* Launch. */ -- ports_manage_port_operations_multithread (fsys->pi.bucket, random_demuxer, -- 10 * 1000, /* idle thread */ -- 10 * 60 * 1000, /* idle server */ -- 0); -- return 0; --} -diff --git a/random/random.h b/random/random.h -deleted file mode 100644 -index a38a417..0000000 ---- a/random/random.h -+++ /dev/null -@@ -1,32 +0,0 @@ --/* random.c - A single-file translator providing random data -- Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc. -- -- 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, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -- --#ifndef __RANDOM_H__ --#define __RANDOM_H__ -- --/* How many random bytes to gather at most. -- XXX: Should be at least POOLSIZE. */ --#define GATHERBUFSIZE 32768 -- --/* The random bytes we collected. */ --extern char gatherbuf[GATHERBUFSIZE]; -- --/* The current positions in gatherbuf[]. */ --extern int gatherrpos; --extern int gatherwpos; -- --#endif -diff --git a/sutils/MAKEDEV.sh b/sutils/MAKEDEV.sh -index 1baec15..9fd4b1d 100644 ---- a/sutils/MAKEDEV.sh -+++ b/sutils/MAKEDEV.sh -@@ -100,7 +100,7 @@ mkdev() { - ;; - - std) -- mkdev console tty urandom null zero full fd time mem klog shm -+ mkdev console tty random urandom null zero full fd time mem klog shm - ;; - console|com[0-9]) - st $I root 600 /hurd/term ${DEVDIR}/$I device $I;; -@@ -111,8 +111,10 @@ mkdev() { - ${DEVDIR}/vcs/`echo $I | sed -e s/tty//`/console;; - lpr[0-9]) - st $I root 660 /hurd/streamio "$I";; -+ random) -+ st $I root 644 /hurd/random --secure --seed-file /var/lib/random-seed;; - urandom) -- st $I root 644 /hurd/random --fast --seed-file /var/lib/random-seed;; -+ st $I root 644 /hurd/random --fast --seed-file /var/lib/urandom-seed;; - null) - st $I root 666 /hurd/null;; - full) -diff --git a/trans/Makefile b/trans/Makefile -index ce1eae7..ec0586e 100644 ---- a/trans/Makefile -+++ b/trans/Makefile -@@ -21,14 +21,14 @@ makemode := servers - - targets = symlink firmlink ifsock magic null fifo new-fifo fwd crash \ - password hello hello-mt streamio fakeroot proxy-defpager remap \ -- mtab -+ mtab random - SRCS = ifsock.c symlink.c magic.c null.c fifo.c new-fifo.c fwd.c \ - crash.c firmlink.c password.c hello.c hello-mt.c streamio.c \ - fakeroot.c proxy-defpager.c remap.c mtab.c - OBJS = $(SRCS:.c=.o) fsysServer.o ifsockServer.o passwordServer.o \ - crashServer.o crash_replyUser.o msgServer.o \ - default_pagerServer.o default_pagerUser.o \ -- device_replyServer.o elfcore.o -+ device_replyServer.o elfcore.o startup_notifyServer.o - HURDLIBS = ports netfs trivfs iohelp fshelp pipe ihash shouldbeinlibc - LDLIBS += -lpthread - password-LDLIBS = -lcrypt -@@ -51,6 +51,8 @@ device_reply-MIGSFLAGS="-DMACH_PAYLOAD_TO_PORT=ports_payload_get_name" - # libports. Disable the default payload to port conversion. - fsys-MIGSFLAGS = "-DHURD_DEFAULT_PAYLOAD_TO_PORT=1" - -+random-LDLIBS = -lgcrypt -+ - include ../Makeconf - - vpath elfcore.c $(top_srcdir)/exec -@@ -71,6 +73,7 @@ hello: ../libtrivfs/libtrivfs.a ../libfshelp/libfshelp.a ../libports/libports.a - fakeroot: ../libnetfs/libnetfs.a ../libfshelp/libfshelp.a ../libiohelp/libiohelp.a ../libports/libports.a ../libihash/libihash.a - remap: ../libtrivfs/libtrivfs.a ../libfshelp/libfshelp.a ../libports/libports.a ../libihash/libihash.a - mtab: ../libtrivfs/libtrivfs.a ../libfshelp/libfshelp.a ../libports/libports.a ../libihash/libihash.a fsUser.o -+random: ../libtrivfs/libtrivfs.a ../libports/libports.a ../libihash/libihash.a startup_notifyServer.o mach_debugUser.o - $(targets): ../libshouldbeinlibc/libshouldbeinlibc.a - - $(targets): %: %.o -diff --git a/trans/random.c b/trans/random.c -new file mode 100644 -index 0000000..83f0579 ---- /dev/null -+++ b/trans/random.c -@@ -0,0 +1,682 @@ -+/* random.c - A single-file translator providing random data -+ Copyright (C) 1998, 1999, 2001, 2015 Free Software Foundation, Inc. -+ -+ 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, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -+ -+#include <argp.h> -+#include <argz.h> -+#include <assert.h> -+#include <error.h> -+#include <fcntl.h> -+#include <gcrypt.h> -+#include <hurd/paths.h> -+#include <hurd/startup.h> -+#include <hurd/trivfs.h> -+#include <mach_debug/mach_debug_types.h> -+#include <pthread.h> -+#include <stdio.h> -+#include <stdlib.h> -+#include <string.h> -+#include <sys/mman.h> -+#include <sys/stat.h> -+#include <unistd.h> -+#include <version.h> -+ -+#include "mach_debug_U.h" -+ -+/* Our control port. */ -+struct trivfs_control *fsys; -+ -+int read_blocked; /* For read and select. */ -+pthread_cond_t wait; /* For read and select. */ -+pthread_cond_t select_alert; /* For read and select. */ -+ -+/* The quality of randomness we provide. If URANDOM is set, return -+ unlimited random data. */ -+static int urandom; -+ -+/* Name of file to use as seed. */ -+static char *seed_file; -+ -+/* Entropy management. */ -+ -+/* Estimate of available entropy measured in bytes. */ -+static size_t entropy; -+ -+/* Protected by this lock. */ -+static pthread_mutex_t entropy_lock; -+ -+static error_t -+entropy_add (const void *buf, size_t length, float factor) -+{ -+ gcry_error_t cerr; -+ size_t new_entropy; -+ pthread_mutex_lock (&entropy_lock); -+ -+ cerr = gcry_random_add_bytes (buf, length, -1); -+ if (cerr) -+ { -+ pthread_mutex_unlock (&entropy_lock); -+ error (0, 0, "Failed to add random bytes: %s", -+ gcry_strerror (cerr)); -+ return EINVAL; -+ } -+ new_entropy = (size_t) ((float) length * factor); -+ entropy += new_entropy; -+ -+ if (new_entropy > 0 && read_blocked) -+ { -+ read_blocked = 0; -+ pthread_cond_broadcast (&wait); -+ pthread_cond_broadcast (&select_alert); -+ } -+ -+ pthread_mutex_unlock (&entropy_lock); -+ return 0; -+} -+ -+static void -+update_random_seed_file (void) -+{ -+ gcry_error_t cerr; -+ cerr = gcry_control (GCRYCTL_UPDATE_RANDOM_SEED_FILE, seed_file, 0); -+ if (cerr) -+ error (0, 0, "Updating random seed file %s failed: %s", -+ seed_file, gcry_strerror (cerr)); -+} -+ -+static void -+initialize_gcrypt (void) -+{ -+ gcry_error_t cerr; -+ struct stat s; -+ -+ if (! gcry_check_version (GCRYPT_VERSION)) -+ error (1, 0, "libgcrypt version mismatch\n"); -+ -+ cerr = gcry_control (GCRYCTL_SET_PREFERRED_RNG_TYPE, -+ GCRY_RNG_TYPE_STANDARD, 0); -+ if (cerr) -+ error (1, 0, "Selecting preferred rng type failed: %s", -+ gcry_strerror (cerr)); -+ -+ cerr = gcry_control (GCRYCTL_SET_RANDOM_SEED_FILE, seed_file, 0); -+ if (cerr) -+ error (1, 0, "Setting seed file %s failed: %s", -+ seed_file, gcry_strerror (cerr)); -+ -+ cerr = gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); -+ if (cerr) -+ error (1, 0, "Finalizing gcrypt failed: %s", -+ gcry_strerror (cerr)); -+ -+ if (stat (seed_file, &s) == 0) -+ /* Libgcrypt will read the seed file on demand. Set entropy -+ accordingly. */ -+ entropy = s.st_size; -+} -+ -+static void -+gather_slab_info (void) -+{ -+ error_t err; -+ cache_info_array_t cache_info; -+ mach_msg_type_number_t cache_info_count, i; -+ -+ cache_info = NULL; -+ cache_info_count = 0; -+ -+ err = host_slab_info (mach_host_self(), &cache_info, &cache_info_count); -+ if (err) -+ { -+ error (0, err, "host_slab_info"); -+ return; -+ } -+ -+ for (i = 0; i < cache_info_count; i++) -+ if (cache_info[i].nr_bufs > 500) -+ entropy_add (&cache_info[i].nr_objs, sizeof cache_info[i].nr_objs, -+ 0.25); -+ -+ vm_deallocate (mach_task_self (), -+ (vm_address_t) cache_info, -+ cache_info_count * sizeof *cache_info); -+} -+ -+static void * -+gather_thread (void *args) -+{ -+ while (1) -+ { -+ gather_slab_info (); -+ sleep (1); /* XXX vary sleep time */ -+ } -+ -+ assert (! "reached"); -+} -+ -+error_t -+start_gather_thread (void) -+{ -+ error_t err; -+ pthread_t thread; -+ -+ err = pthread_create (&thread, NULL, gather_thread, NULL); -+ if (err) -+ return err; -+ -+ err = pthread_detach (thread); -+ return err; -+} -+ -+const char *argp_program_version = STANDARD_HURD_VERSION (random); -+ -+/* Trivfs hooks. */ -+int trivfs_fstype = FSTYPE_MISC; -+int trivfs_fsid = 0; -+ -+int trivfs_allow_open = O_READ | O_WRITE; -+ -+int trivfs_support_read = 1; -+int trivfs_support_write = 1; -+int trivfs_support_exec = 0; -+ -+void -+trivfs_modify_stat (struct trivfs_protid *cred, struct stat *st) -+{ -+ /* Mark the node as a read-only plain file. */ -+ st->st_mode &= ~((unsigned) S_IFMT); -+ st->st_mode |= (S_IFCHR); -+ st->st_size = 0; -+} -+ -+error_t -+trivfs_goaway (struct trivfs_control *cntl, int flags) -+{ -+ update_random_seed_file (); -+ exit (0); -+} -+ -+/* Read data from an IO object. If offset is -1, read from the object -+ maintained file pointer. If the object is not seekable, offset is -+ ignored. The amount desired to be read is in AMOUNT. */ -+error_t -+trivfs_S_io_read (struct trivfs_protid *cred, -+ mach_port_t reply, mach_msg_type_name_t reply_type, -+ data_t *data, mach_msg_type_number_t *data_len, -+ loff_t offs, mach_msg_type_number_t amount) -+{ -+ error_t err; -+ void *buf = NULL; -+ size_t length = 0; -+ -+ if (! cred) -+ return EOPNOTSUPP; -+ else if (! (cred->po->openmodes & O_READ)) -+ return EBADF; -+ -+ pthread_mutex_lock (&entropy_lock); -+ -+ if (amount > 0) -+ { -+ while (! urandom && amount > entropy) -+ { -+ if (cred->po->openmodes & O_NONBLOCK) -+ { -+ err = EWOULDBLOCK; -+ goto errout; -+ } -+ read_blocked = 1; -+ if (pthread_hurd_cond_wait_np (&wait, &entropy_lock)) -+ { -+ err = EINTR; -+ goto errout; -+ } -+ /* See term/users.c for possible race? */ -+ } -+ -+ /* Possibly allocate a new buffer. */ -+ if (*data_len < amount) -+ { -+ *data = mmap (0, amount, PROT_READ|PROT_WRITE, -+ MAP_ANON, 0, 0); -+ -+ if (*data == MAP_FAILED) -+ { -+ pthread_mutex_unlock (&entropy_lock); -+ return errno; -+ } -+ -+ /* Keep track of our map in case of errors. */ -+ buf = *data, length = amount; -+ -+ /* Update DATA_LEN to reflect the new buffers size. */ -+ *data_len = amount; -+ } -+ -+ if (! urandom) -+ assert (entropy >= amount); -+ else if (entropy >= amount) -+ entropy -= amount; -+ else -+ entropy = 0; -+ -+ gcry_randomize ((unsigned char *) *data, amount, GCRY_STRONG_RANDOM); -+ } -+ -+ /* Set atime, see term/users.c */ -+ -+ pthread_mutex_unlock (&entropy_lock); -+ *data_len = amount; -+ return 0; -+ -+ errout: -+ pthread_mutex_unlock (&entropy_lock); -+ if (buf) -+ munmap (buf, length); -+ return err; -+} -+ -+/* Write data to an IO object. If offset is -1, write at the object -+ maintained file pointer. If the object is not seekable, offset is -+ ignored. The amount successfully written is returned in amount. A -+ given user should not have more than one outstanding io_write on an -+ object at a time; servers implement congestion control by delaying -+ responses to io_write. Servers may drop data (returning ENOBUFS) -+ if they receive more than one write when not prepared for it. */ -+error_t -+trivfs_S_io_write (struct trivfs_protid *cred, -+ mach_port_t reply, -+ mach_msg_type_name_t replytype, -+ data_t data, -+ mach_msg_type_number_t datalen, -+ loff_t offset, -+ mach_msg_type_number_t *amount) -+{ -+ error_t err; -+ -+ /* Deny access if they have bad credentials. */ -+ if (! cred) -+ return EOPNOTSUPP; -+ else if (! (cred->po->openmodes & O_WRITE)) -+ return EBADF; -+ -+ err = entropy_add (data, datalen, 0); -+ *amount = datalen; -+ return err; -+} -+ -+/* Tell how much data can be read from the object without blocking for -+ a "long time" (this should be the same meaning of "long time" used -+ by the nonblocking flag. */ -+kern_return_t -+trivfs_S_io_readable (struct trivfs_protid *cred, -+ mach_port_t reply, mach_msg_type_name_t replytype, -+ mach_msg_type_number_t *amount) -+{ -+ /* Deny access if they have bad credentials. */ -+ if (! cred) -+ return EOPNOTSUPP; -+ else if (! (cred->po->openmodes & O_READ)) -+ return EBADF; -+ -+ pthread_mutex_lock (&entropy_lock); -+ -+ *amount = entropy; -+ -+ pthread_mutex_unlock (&entropy_lock); -+ -+ return 0; -+} -+ -+/* SELECT_TYPE is the bitwise OR of SELECT_READ, SELECT_WRITE, and SELECT_URG. -+ Block until one of the indicated types of i/o can be done "quickly", and -+ return the types that are then available. ID_TAG is returned as passed; it -+ is just for the convenience of the user in matching up reply messages with -+ specific requests sent. */ -+error_t -+trivfs_S_io_select (struct trivfs_protid *cred, -+ mach_port_t reply, -+ mach_msg_type_name_t reply_type, -+ int *type) -+{ -+ if (!cred) -+ return EOPNOTSUPP; -+ -+ /* We only deal with SELECT_READ and SELECT_WRITE here. */ -+ if (*type & ~(SELECT_READ | SELECT_WRITE)) -+ return EINVAL; -+ -+ if (*type == 0) -+ return 0; -+ -+ pthread_mutex_lock (&entropy_lock); -+ -+ while (1) -+ { -+ if (entropy > 0 || *type & SELECT_WRITE) -+ { -+ *type = (entropy > 0 ? SELECT_READ : 0) | (*type & SELECT_WRITE); -+ pthread_mutex_unlock (&entropy_lock); -+ return 0; -+ } -+ -+ ports_interrupt_self_on_port_death (cred, reply); -+ read_blocked = 1; -+ -+ if (pthread_hurd_cond_wait_np (&select_alert, &entropy_lock)) -+ { -+ *type = 0; -+ pthread_mutex_unlock (&entropy_lock); -+ return EINTR; -+ } -+ } -+} -+ -+ -+/* Change current read/write offset */ -+error_t -+trivfs_S_io_seek (struct trivfs_protid *cred, -+ mach_port_t reply, mach_msg_type_name_t reply_type, -+ loff_t offs, int whence, loff_t *new_offs) -+{ -+ if (! cred) -+ return EOPNOTSUPP; -+ -+ /* Not seekable. */ -+ return ESPIPE; -+} -+ -+/* Change the size of the file. If the size increases, new blocks are -+ zero-filled. After successful return, it is safe to reference mapped -+ areas of the file up to NEW_SIZE. */ -+error_t -+trivfs_S_file_set_size (struct trivfs_protid *cred, -+ mach_port_t reply, mach_msg_type_name_t reply_type, -+ loff_t size) -+{ -+ if (!cred) -+ return EOPNOTSUPP; -+ -+ return size == 0 ? 0 : EINVAL; -+} -+ -+/* These four routines modify the O_APPEND, O_ASYNC, O_FSYNC, and -+ O_NONBLOCK bits for the IO object. In addition, io_get_openmodes -+ will tell you which of O_READ, O_WRITE, and O_EXEC the object can -+ be used for. The O_ASYNC bit affects icky async I/O; good async -+ I/O is done through io_async which is orthogonal to these calls. */ -+error_t -+trivfs_S_io_set_all_openmodes(struct trivfs_protid *cred, -+ mach_port_t reply, -+ mach_msg_type_name_t reply_type, -+ int mode) -+{ -+ if (!cred) -+ return EOPNOTSUPP; -+ -+ return 0; -+} -+ -+error_t -+trivfs_S_io_set_some_openmodes (struct trivfs_protid *cred, -+ mach_port_t reply, -+ mach_msg_type_name_t reply_type, -+ int bits) -+{ -+ if (!cred) -+ return EOPNOTSUPP; -+ -+ return 0; -+} -+ -+error_t -+trivfs_S_io_get_owner (struct trivfs_protid *cred, -+ mach_port_t reply, -+ mach_msg_type_name_t reply_type, -+ pid_t *owner) -+{ -+ if (!cred) -+ return EOPNOTSUPP; -+ -+ *owner = 0; -+ return 0; -+} -+ -+error_t -+trivfs_S_io_mod_owner (struct trivfs_protid *cred, -+ mach_port_t reply, mach_msg_type_name_t reply_type, -+ pid_t owner) -+{ -+ if (!cred) -+ return EOPNOTSUPP; -+ -+ return EINVAL; -+} -+ -+/* Return objects mapping the data underlying this memory object. If -+ the object can be read then memobjrd will be provided; if the -+ object can be written then memobjwr will be provided. For objects -+ where read data and write data are the same, these objects will be -+ equal, otherwise they will be disjoint. Servers are permitted to -+ implement io_map but not io_map_cntl. Some objects do not provide -+ mapping; they will set none of the ports and return an error. Such -+ objects can still be accessed by io_read and io_write. */ -+error_t -+trivfs_S_io_map(struct trivfs_protid *cred, -+ mach_port_t reply, mach_msg_type_name_t reply_type, -+ mach_port_t *rdobj, -+ mach_msg_type_name_t *rdtype, -+ mach_port_t *wrobj, -+ mach_msg_type_name_t *wrtype) -+{ -+ if (!cred) -+ return EOPNOTSUPP; -+ -+ return EINVAL; -+} -+ -+ -+int -+random_demuxer (mach_msg_header_t *inp, -+ mach_msg_header_t *outp) -+{ -+ extern int startup_notify_server (mach_msg_header_t *, mach_msg_header_t *); -+ -+ return (trivfs_demuxer (inp, outp) -+ || startup_notify_server (inp, outp)); -+} -+ -+ -+/* Options processing. We accept the same options on the command line -+ and from fsys_set_options. */ -+ -+static const struct argp_option options[] = -+{ -+ {"fast", 'f', 0, 0, "Output cheap random data fast"}, -+ {"secure", 's', 0, 0, -+ "Output cryptographically secure random (the default)"}, -+ {"seed-file", 'S', "FILE", 0, "Use FILE to remember the seed"}, -+ {0} -+}; -+ -+static error_t -+parse_opt (int opt, char *arg, struct argp_state *state) -+{ -+ switch (opt) -+ { -+ default: -+ return ARGP_ERR_UNKNOWN; -+ case ARGP_KEY_INIT: -+ case ARGP_KEY_SUCCESS: -+ case ARGP_KEY_ERROR: -+ break; -+ -+ case 'f': -+ urandom = 1; -+ break; -+ -+ case 's': -+ urandom = 0; -+ break; -+ -+ case 'S': -+ seed_file = strdup (arg); -+ break; -+ } -+ return 0; -+} -+ -+/* This will be called from libtrivfs to help construct the answer -+ to an fsys_get_options RPC. */ -+error_t -+trivfs_append_args (struct trivfs_control *fsys, -+ char **argz, size_t *argz_len) -+{ -+ error_t err = 0; -+ char *opt; -+ -+ err = argz_add (argz, argz_len, urandom ? "--fast" : "--secure"); -+ if (err) -+ return err; -+ -+ if (seed_file) -+ { -+ if (asprintf (&opt, "--seed-file=%s", seed_file) < 0) -+ err = ENOMEM; -+ else -+ { -+ err = argz_add (argz, argz_len, opt); -+ free (opt); -+ } -+ } -+ -+ return err; -+} -+ -+static struct argp random_argp = -+{ options, parse_opt, 0, -+ "A translator providing random output." }; -+ -+/* Setting this variable makes libtrivfs use our argp to -+ parse options passed in an fsys_set_options RPC. */ -+struct argp *trivfs_runtime_argp = &random_argp; -+ -+struct port_class *shutdown_notify_class; -+ -+/* The system is going down; destroy all the extant port rights. That -+ will cause net channels and such to close promptly. */ -+error_t -+S_startup_dosync (mach_port_t handle) -+{ -+ struct port_info *inpi = ports_lookup_port (fsys->pi.bucket, handle, -+ shutdown_notify_class); -+ -+ if (!inpi) -+ return EOPNOTSUPP; -+ -+ update_random_seed_file (); -+ return 0; -+} -+ -+void -+sigterm_handler (int signo) -+{ -+ update_random_seed_file (); -+ signal (SIGTERM, SIG_DFL); -+ raise (SIGTERM); -+} -+ -+static error_t -+arrange_shutdown_notification () -+{ -+ error_t err; -+ mach_port_t initport, notify; -+ struct port_info *pi; -+ -+ shutdown_notify_class = ports_create_class (0, 0); -+ -+ signal (SIGTERM, sigterm_handler); -+ -+ /* Arrange to get notified when the system goes down, -+ but if we fail for some reason, just silently give up. No big deal. */ -+ -+ err = ports_create_port (shutdown_notify_class, fsys->pi.bucket, -+ sizeof (struct port_info), &pi); -+ if (err) -+ return err; -+ -+ initport = file_name_lookup (_SERVERS_STARTUP, 0, 0); -+ if (! MACH_PORT_VALID (initport)) -+ return errno; -+ -+ notify = ports_get_send_right (pi); -+ ports_port_deref (pi); -+ err = startup_request_notification (initport, notify, -+ MACH_MSG_TYPE_MAKE_SEND, -+ program_invocation_short_name); -+ -+ mach_port_deallocate (mach_task_self (), notify); -+ mach_port_deallocate (mach_task_self (), initport); -+ return err; -+} -+ -+int -+main (int argc, char **argv) -+{ -+ error_t err; -+ mach_port_t bootstrap; -+ -+ /* Initialize the lock that will protect everything. -+ We must do this before argp_parse, because parse_opt (above) will -+ use the lock. */ -+ pthread_mutex_init (&entropy_lock, NULL); -+ -+ /* The conditions are used to implement proper read/select -+ behaviour. */ -+ pthread_cond_init (&wait, NULL); -+ pthread_cond_init (&select_alert, NULL); -+ -+ /* We use the same argp for options available at startup -+ as for options we'll accept in an fsys_set_options RPC. */ -+ argp_parse (&random_argp, argc, argv, 0, 0, 0); -+ -+ initialize_gcrypt (); -+ -+ task_get_bootstrap_port (mach_task_self (), &bootstrap); -+ if (bootstrap == MACH_PORT_NULL) -+ error (1, 0, "Must be started as a translator"); -+ -+ /* Reply to our parent */ -+ err = trivfs_startup (bootstrap, 0, 0, 0, 0, 0, &fsys); -+ mach_port_deallocate (mach_task_self (), bootstrap); -+ if (err) -+ error (3, err, "trivfs_startup"); -+ -+ err = arrange_shutdown_notification (); -+ if (err) -+ error (0, err, "Cannot request shutdown notification"); -+ -+ err = start_gather_thread (); -+ if (err) -+ error (0, err, "Starting gatherer thread failed"); -+ -+ /* Launch. */ -+ ports_manage_port_operations_multithread (fsys->pi.bucket, random_demuxer, -+ 10 * 1000, /* idle thread */ -+ 10 * 60 * 1000, /* idle server */ -+ 0); -+ return 0; -+} --- -2.1.4 - diff --git a/debian/patches/series b/debian/patches/series index 6f4eeb34..66ea1767 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -1,4 +1,3 @@ -random0001-xxx-standalone-random-translator.patch diskfs_no_inherit_dir_group.patch init_try_runsystem.gnu.patch makedev.diff |