diff options
author | Justus Winter <4winter@informatik.uni-hamburg.de> | 2015-11-27 19:04:02 +0100 |
---|---|---|
committer | Justus Winter <4winter@informatik.uni-hamburg.de> | 2015-11-27 19:04:02 +0100 |
commit | 0b15396767873044cc30cfca03f3ae324e03a36f (patch) | |
tree | 7c4af93d27bcb851f9c316dd0dfab2f1588bf2d2 /debian/patches/random0001-xxx-standalone-random-translator.patch | |
parent | 248c87f2ed7f3daaec3d8fef53ee4bb02c1bb837 (diff) |
add patch series
Diffstat (limited to 'debian/patches/random0001-xxx-standalone-random-translator.patch')
-rw-r--r-- | debian/patches/random0001-xxx-standalone-random-translator.patch | 3209 |
1 files changed, 3209 insertions, 0 deletions
diff --git a/debian/patches/random0001-xxx-standalone-random-translator.patch b/debian/patches/random0001-xxx-standalone-random-translator.patch new file mode 100644 index 00000000..54ad5e07 --- /dev/null +++ b/debian/patches/random0001-xxx-standalone-random-translator.patch @@ -0,0 +1,3209 @@ +From 79d0a389ba6e9aacc93839538c27a81424a92521 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 | 677 +++++++++++++++++++++++++++++++++++++++++ + 14 files changed, 686 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..f619260 +--- /dev/null ++++ b/trans/random.c +@@ -0,0 +1,677 @@ ++/* 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; ++ } ++ ++ assert (entropy >= amount); ++ gcry_randomize ((unsigned char *) *data, amount, GCRY_STRONG_RANDOM); ++ entropy -= amount; ++ } ++ ++ /* 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 + |