X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=lib%2Fsilccrypt%2Fsilcrng.c;h=e9fe1c81ffe3d596b1572aeafa355104f388a2dc;hb=017dec75a98209fbef49eb496c2269b0c49e736d;hp=5f0230ccc167de1edf0f52f29872a76504df8abe;hpb=72cfa31520ebc0058763a30e21c13f6e9a964aa0;p=silc.git diff --git a/lib/silccrypt/silcrng.c b/lib/silccrypt/silcrng.c index 5f0230cc..e9fe1c81 100644 --- a/lib/silccrypt/silcrng.c +++ b/lib/silccrypt/silcrng.c @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 1997 - 2000 Pekka Riikonen + Copyright (C) 1997 - 2001 Pekka Riikonen 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 @@ -21,21 +21,25 @@ /* * Created: Sun Mar 9 00:09:18 1997 * - * This RNG is based on Secure Shell's random number generator. + * The original RNG was based on Secure Shell's random number generator + * by Tatu Ylönen and was used as reference when programming this RNG. + * This RNG has been rewritten twice since the creation. */ -/* XXX: Some operations block resulting slow initialization. - * XXX: I have some pending changes to make this better. */ #include "silcincludes.h" #undef SILC_RNG_DEBUG -/* #define SILC_RNG_DEBUG */ +/*#define SILC_RNG_DEBUG*/ + +/* Number of states to fetch data from pool. */ +#define SILC_RNG_STATE_NUM 4 + +/* Byte size of the random data pool. */ +#define SILC_RNG_POOLSIZE 1024 static uint32 silc_rng_get_position(SilcRng rng); static void silc_rng_stir_pool(SilcRng rng); static void silc_rng_xor(SilcRng rng, uint32 val, unsigned int pos); -static void silc_rng_add_noise(SilcRng rng, unsigned char *buffer, - uint32 len); static void silc_rng_exec_command(SilcRng rng, char *command); static void silc_rng_get_hard_noise(SilcRng rng); static void silc_rng_get_medium_noise(SilcRng rng); @@ -98,12 +102,19 @@ typedef struct SilcRngStateContext { random pool. This is allocated when RNG object is allocated and free'd when RNG object is free'd. + uint8 threshhold + + Threshhold to indicate when it is required to acquire more + noise from the environment. More soft noise is acquired after + 64 bits of output and hard noise every 160 bits of output. + */ typedef struct SilcRngObjectStruct { unsigned char pool[SILC_RNG_POOLSIZE]; unsigned char key[64]; SilcRngState state; SilcHash sha1; + uint8 threshhold; } SilcRngObject; /* Allocates new RNG object. */ @@ -173,39 +184,69 @@ void silc_rng_init(SilcRng rng) silc_rng_get_soft_noise(rng); silc_rng_get_medium_noise(rng); silc_rng_get_hard_noise(rng); + silc_rng_get_soft_noise(rng); } /* This function gets 'soft' noise from environment. */ static void silc_rng_get_soft_noise(SilcRng rng) { +#ifndef SILC_WIN32 struct tms ptime; +#endif + uint32 pos; + pos = silc_rng_get_position(rng); + silc_rng_xor(rng, clock(), 0); +#ifndef SILC_WIN32 +#ifdef HAVE_GETPID silc_rng_xor(rng, getpid(), 1); - silc_rng_xor(rng, getpgid(getpid() << 8), 2); - silc_rng_xor(rng, getpgid(getpid() << 8), 3); +#ifdef HAVE_GETPGID + silc_rng_xor(rng, getpgid(getpid()) << 8, 2); + silc_rng_xor(rng, getpgid(getpid()) << 8, 3); +#endif silc_rng_xor(rng, getgid(), 4); +#endif +#ifdef HAVE_GETPGRP silc_rng_xor(rng, getpgrp(), 5); - silc_rng_xor(rng, getsid(getpid() << 16), 6); +#endif +#ifdef HAVE_GETSID + silc_rng_xor(rng, getsid(getpid()) << 16, 6); +#endif silc_rng_xor(rng, times(&ptime), 7); silc_rng_xor(rng, ptime.tms_utime, 8); - silc_rng_xor(rng, (ptime.tms_utime + ptime.tms_stime), 9); - silc_rng_xor(rng, (ptime.tms_stime + ptime.tms_cutime), 10); - silc_rng_xor(rng, (ptime.tms_utime + ptime.tms_stime), 11); - silc_rng_xor(rng, (ptime.tms_cutime ^ ptime.tms_stime), 12); - silc_rng_xor(rng, (ptime.tms_cutime ^ ptime.tms_cstime), 13); - silc_rng_xor(rng, (ptime.tms_utime ^ ptime.tms_stime), 14); - silc_rng_xor(rng, (ptime.tms_stime ^ ptime.tms_cutime), 15); - silc_rng_xor(rng, (ptime.tms_cutime + ptime.tms_stime), 16); - silc_rng_xor(rng, (ptime.tms_stime << 8), 17); - silc_rng_xor(rng, clock() << 4, 18); - silc_rng_xor(rng, getpgid(getpid() << 8), 19); - silc_rng_xor(rng, getpgrp(), 20); - silc_rng_xor(rng, getsid(getpid() << 16), 21); - silc_rng_xor(rng, times(&ptime), 22); - silc_rng_xor(rng, ptime.tms_utime, 23); - silc_rng_xor(rng, getpgrp(), 24); + silc_rng_xor(rng, (ptime.tms_utime + ptime.tms_stime), pos++); + silc_rng_xor(rng, (ptime.tms_stime + ptime.tms_cutime), pos++); + silc_rng_xor(rng, (ptime.tms_utime + ptime.tms_stime), pos++); + silc_rng_xor(rng, (ptime.tms_cutime ^ ptime.tms_stime), pos++); + silc_rng_xor(rng, (ptime.tms_cutime ^ ptime.tms_cstime), pos++); + silc_rng_xor(rng, (ptime.tms_utime ^ ptime.tms_stime), pos++); + silc_rng_xor(rng, (ptime.tms_stime ^ ptime.tms_cutime), pos++); + silc_rng_xor(rng, (ptime.tms_cutime + ptime.tms_stime), pos++); + silc_rng_xor(rng, (ptime.tms_stime << 8), pos++); +#endif + silc_rng_xor(rng, clock() << 4, pos++); +#ifndef SILC_WIN32 +#ifdef HAVE_GETPGID + silc_rng_xor(rng, getpgid(getpid()) << 8, pos++); +#endif +#ifdef HAVE_GETPGRP + silc_rng_xor(rng, getpgrp(), pos++); +#endif +#ifdef HAVE_SETSID + silc_rng_xor(rng, getsid(getpid()) << 16, pos++); +#endif + silc_rng_xor(rng, times(&ptime), pos++); + silc_rng_xor(rng, ptime.tms_utime, pos++); +#ifdef HAVE_GETPGRP + silc_rng_xor(rng, getpgrp(), pos++); +#endif +#endif + +#ifdef SILC_RNG_DEBUG + SILC_LOG_HEXDUMP(("pool"), rng->pool, sizeof(rng->pool)); +#endif /* Stir random pool */ silc_rng_stir_pool(rng); @@ -215,14 +256,14 @@ static void silc_rng_get_soft_noise(SilcRng rng) static void silc_rng_get_medium_noise(SilcRng rng) { - silc_rng_exec_command(rng, "ps -lefaww 2> /dev/null"); - silc_rng_exec_command(rng, "ls -afiln 2> /dev/null"); - silc_rng_exec_command(rng, "ps -asww 2> /dev/null"); + silc_rng_exec_command(rng, "ps -leaww 2> /dev/null"); + silc_rng_exec_command(rng, "ls -afiln ~ 2> /dev/null"); silc_rng_exec_command(rng, "ls -afiln /proc 2> /dev/null"); - /* - silc_rng_exec_command(rng, "ps -ef 2> /dev/null"); - silc_rng_exec_command(rng, "ls -alin /dev 2> /dev/null"); - */ + silc_rng_exec_command(rng, "ps -axww 2> /dev/null"); + +#ifdef SILC_RNG_DEBUG + SILC_LOG_HEXDUMP(("pool"), rng->pool, sizeof(rng->pool)); +#endif } /* This function gets 'hard' noise from environment. This tries to @@ -230,6 +271,7 @@ static void silc_rng_get_medium_noise(SilcRng rng) static void silc_rng_get_hard_noise(SilcRng rng) { +#ifndef SILC_WIN32 char buf[32]; int fd, len, i; @@ -240,23 +282,29 @@ static void silc_rng_get_hard_noise(SilcRng rng) fcntl(fd, F_SETFL, O_NONBLOCK); - for (i = 0; i < 8; i++) { + for (i = 0; i < 2; i++) { len = read(fd, buf, sizeof(buf)); if (len <= 0) goto out; silc_rng_add_noise(rng, buf, len); } +#ifdef SILC_RNG_DEBUG + SILC_LOG_HEXDUMP(("pool"), rng->pool, sizeof(rng->pool)); +#endif + out: close(fd); memset(buf, 0, sizeof(buf)); +#endif } /* Execs command and gets noise from its output */ static void silc_rng_exec_command(SilcRng rng, char *command) { - char buf[2048]; +#ifndef SILC_WIN32 + char buf[1024]; FILE *fd; int i; int c; @@ -282,13 +330,13 @@ static void silc_rng_exec_command(SilcRng rng, char *command) /* Add the buffer into random pool */ silc_rng_add_noise(rng, buf, strlen(buf)); memset(buf, 0, sizeof(buf)); +#endif } /* This function adds the contents of the buffer as noise into random pool. After adding the noise the pool is stirred. */ -static void silc_rng_add_noise(SilcRng rng, unsigned char *buffer, - uint32 len) +void silc_rng_add_noise(SilcRng rng, unsigned char *buffer, uint32 len) { uint32 i, pos; @@ -365,7 +413,7 @@ static uint32 silc_rng_get_position(SilcRng rng) rng->state->pos = rng->state->low; #ifdef SILC_RNG_DEBUG - fprintf(stderr, "state: %p: low: %d, pos: %d\n", + fprintf(stderr, "state: %p: low: %lu, pos: %lu\n", rng->state, rng->state->low, rng->state->pos); #endif @@ -374,10 +422,22 @@ static uint32 silc_rng_get_position(SilcRng rng) return pos; } -/* returns random byte. Every two byte is from pools low or high state. */ +/* Returns random byte. */ unsigned char silc_rng_get_byte(SilcRng rng) { + rng->threshhold++; + + /* Get more soft noise after 64 bits threshhold */ + if (rng->threshhold >= 8) + silc_rng_get_soft_noise(rng); + + /* Get hard noise after 160 bits threshhold, zero the threshhold. */ + if (rng->threshhold >= 20) { + rng->threshhold = 0; + silc_rng_get_hard_noise(rng); + } + return rng->pool[silc_rng_get_position(rng)]; } @@ -499,3 +559,9 @@ unsigned char *silc_rng_global_get_rn_data(uint32 len) { return global_rng ? silc_rng_get_rn_data(global_rng, len) : NULL; } + +void silc_rng_global_add_noise(unsigned char *buffer, uint32 len) +{ + if (global_rng) + silc_rng_add_noise(global_rng, buffer, len); +}