* Created: Sun Mar 9 00:09:18 1997
*
* The original RNG was based on Secure Shell's random number generator
- * by Tatu Ylönen. This RNG has been rewritten twice since the creation.
+ * by Tatu Ylönen and was used as reference when programming this RNG.
+ * This RNG has been rewritten twice since the creation.
*/
#include "silcincludes.h"
+#ifndef WIN32
+#ifdef HAVE_GETSID
+extern pid_t getsid (pid_t __pid);
+#endif
+
+#ifdef HAVE_GETPGID
+extern pid_t getpgid (pid_t __pid);
+#endif
+#endif
+
#undef SILC_RNG_DEBUG
/*#define SILC_RNG_DEBUG*/
SilcRngState state;
SilcHash sha1;
uint8 threshhold;
+ char *devrandom;
+ int fd_devurandom;
} SilcRngObject;
/* Allocates new RNG object. */
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));
new->state = NULL;
silc_hash_alloc("sha1", &new->sha1);
+ new->devrandom = strdup("/dev/random");
+
return new;
}
if (rng) {
memset(rng->pool, 0, sizeof(rng->pool));
memset(rng->key, 0, sizeof(rng->key));
- silc_free(rng->sha1);
+ silc_hash_free(rng->sha1);
+ silc_free(rng->devrandom);
+
+ if (rng->fd_devurandom != -1)
+ close(rng->fd_devurandom);
+
silc_free(rng);
}
}
silc_rng_get_medium_noise(rng);
silc_rng_get_hard_noise(rng);
silc_rng_get_soft_noise(rng);
+ silc_free(rng->devrandom);
+ rng->devrandom = strdup("/dev/urandom");
}
/* 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);
#ifdef HAVE_GETPGID
- silc_rng_xor(rng, getpgid(getpid() << 8), 2);
- silc_rng_xor(rng, getpgid(getpid() << 8), 3);
+ silc_rng_xor(rng, getpgid(getpid()) << 8, 2);
+ silc_rng_xor(rng, getpgid(getpid()) << 8, 3);
#endif
silc_rng_xor(rng, getgid(), 4);
#endif
silc_rng_xor(rng, getpgrp(), 5);
#endif
#ifdef HAVE_GETSID
- silc_rng_xor(rng, getsid(getpid() << 16), 6);
+ 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_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++);
+ 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++);
+ 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));
static void silc_rng_get_hard_noise(SilcRng rng)
{
- char buf[32];
+#ifndef SILC_WIN32
+ unsigned char buf[32];
int fd, len, i;
- /* Get noise from /dev/random if available */
- fd = open("/dev/random", O_RDONLY);
+ /* Get noise from /dev/[u]random if available */
+ fd = open(rng->devrandom, O_RDONLY);
if (fd < 0)
return;
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[1024];
+#ifndef SILC_WIN32
+ unsigned char buf[1024];
FILE *fd;
int i;
int c;
pclose(fd);
/* Add the buffer into random pool */
- silc_rng_add_noise(rng, buf, strlen(buf));
+ silc_rng_add_noise(rng, buf, i);
memset(buf, 0, sizeof(buf));
+#endif
}
/* This function adds the contents of the buffer as noise into random
uint32 iv[5];
/* Get the IV */
- memcpy(iv, &rng->pool[SILC_RNG_POOLSIZE - 256], sizeof(iv));
+ memcpy(iv, &rng->pool[16], sizeof(iv));
/* First CFB pass */
for (i = 0; i < SILC_RNG_POOLSIZE; i += 5) {
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;