X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=lib%2Fsilccrypt%2Fsilcrng.c;h=a52b4eea9efba6cb6b7d7f0fe253918e52aad8c0;hb=b3c198997d2adb79fb3c2e48cba9d0511badd9f0;hp=67ee08fe47d9277da047bb2f16830a98cb5ca5fb;hpb=044263b77b2a2bf97011e7d100dd5ccccf8ca873;p=silc.git diff --git a/lib/silccrypt/silcrng.c b/lib/silccrypt/silcrng.c index 67ee08fe..a52b4eea 100644 --- a/lib/silccrypt/silcrng.c +++ b/lib/silccrypt/silcrng.c @@ -116,6 +116,7 @@ typedef struct SilcRngObjectStruct { SilcHash sha1; uint8 threshhold; char *devrandom; + int fd_devurandom; } SilcRngObject; /* Allocates new RNG object. */ @@ -127,6 +128,7 @@ SilcRng silc_rng_alloc() SILC_LOG_DEBUG(("Allocating new RNG object")); new = silc_calloc(1, sizeof(*new)); + new->fd_devurandom = -1; memset(new->pool, 0, sizeof(new->pool)); memset(new->key, 0, sizeof(new->key)); @@ -147,6 +149,10 @@ void silc_rng_free(SilcRng rng) memset(rng->key, 0, sizeof(rng->key)); silc_hash_free(rng->sha1); silc_free(rng->devrandom); + + if (rng->fd_devurandom != -1) + close(rng->fd_devurandom); + silc_free(rng); } } @@ -278,7 +284,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]; + unsigned char buf[32]; int fd, len, i; /* Get noise from /dev/[u]random if available */ @@ -310,7 +316,7 @@ static void silc_rng_get_hard_noise(SilcRng rng) static void silc_rng_exec_command(SilcRng rng, char *command) { #ifndef SILC_WIN32 - char buf[1024]; + unsigned char buf[1024]; FILE *fd; int i; int c; @@ -546,6 +552,33 @@ unsigned char silc_rng_global_get_byte() return global_rng ? silc_rng_get_byte(global_rng) : 0; } +/* Return random byte as fast as possible. Reads from /dev/urandom if + available. If not then return from normal RNG (not so fast). */ + +unsigned char silc_rng_global_get_byte_fast() +{ +#ifndef SILC_WIN32 + unsigned char buf[1]; + + if (!global_rng) + return 0; + + if (global_rng->fd_devurandom == -1) { + global_rng->fd_devurandom = open("/dev/urandom", O_RDONLY); + if (global_rng < 0) + return silc_rng_global_get_byte(); + fcntl(global_rng->fd_devurandom, F_SETFL, O_NONBLOCK); + } + + if (read(global_rng->fd_devurandom, buf, sizeof(buf)) < 0) + return silc_rng_global_get_byte(); + + return buf[0]; +#else + return silc_rng_global_get_byte(); +#endif +} + uint16 silc_rng_global_get_rn16() { return global_rng ? silc_rng_get_rn16(global_rng) : 0;