/*
- silcrng.c
+ silcrng.c
- Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+ Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2001 Pekka Riikonen
+ Copyright (C) 1997 - 2002 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
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
+ the Free Software Foundation; version 2 of the License.
+
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
#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*/
random pool. This is allocated when RNG object is allocated and
free'd when RNG object is free'd.
- uint8 threshhold
+ uint8 threshold
- Threshhold to indicate when it is required to acquire more
+ Threshold 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 {
+struct SilcRngStruct {
unsigned char pool[SILC_RNG_POOLSIZE];
unsigned char key[64];
SilcRngState state;
SilcHash sha1;
- uint8 threshhold;
+ uint8 threshold;
char *devrandom;
-} SilcRngObject;
+ int fd_devurandom;
+};
/* Allocates new RNG object. */
-SilcRng silc_rng_alloc()
+SilcRng silc_rng_alloc(void)
{
SilcRng new;
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);
+ if (!silc_hash_alloc("sha1", &new->sha1)) {
+ silc_free(new);
+ SILC_LOG_ERROR(("Could not allocate sha1 hash, probably not registered"));
+ return NULL;
+ }
new->devrandom = strdup("/dev/random");
memset(rng->pool, 0, sizeof(rng->pool));
memset(rng->key, 0, sizeof(rng->key));
silc_hash_free(rng->sha1);
- silc_free(new->devrandom);
+ silc_free(rng->devrandom);
+
+ if (rng->fd_devurandom != -1)
+ close(rng->fd_devurandom);
+
silc_free(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 */
- fd = open(rnd->devrandom, O_RDONLY);
+ fd = open(rng->devrandom, O_RDONLY);
if (fd < 0)
return;
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;
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
}
/* Returns random byte. */
-unsigned char silc_rng_get_byte(SilcRng rng)
+uint8 silc_rng_get_byte(SilcRng rng)
{
- rng->threshhold++;
+ rng->threshold++;
- /* Get more soft noise after 64 bits threshhold */
- if (rng->threshhold >= 8)
+ /* Get more soft noise after 64 bits threshold */
+ if (rng->threshold >= 8)
silc_rng_get_soft_noise(rng);
- /* Get hard noise after 160 bits threshhold, zero the threshhold. */
- if (rng->threshhold >= 20) {
- rng->threshhold = 0;
+ /* Get hard noise after 160 bits threshold, zero the threshold. */
+ if (rng->threshold >= 20) {
+ rng->threshold = 0;
silc_rng_get_hard_noise(rng);
}
/* Initialize global RNG. If `rng' is provided it is set as the global
RNG object (it can be allocated by the application for example). */
-int silc_rng_global_init(SilcRng rng)
+bool silc_rng_global_init(SilcRng rng)
{
if (rng)
global_rng = rng;
/* Uninitialize global RNG */
-int silc_rng_global_uninit()
+bool silc_rng_global_uninit(void)
{
if (global_rng) {
silc_rng_free(global_rng);
/* These are analogous to the functions above. */
-unsigned char silc_rng_global_get_byte()
+uint8 silc_rng_global_get_byte(void)
{
return global_rng ? silc_rng_get_byte(global_rng) : 0;
}
-uint16 silc_rng_global_get_rn16()
+/* Return random byte as fast as possible. Reads from /dev/urandom if
+ available. If not then return from normal RNG (not so fast). */
+
+uint8 silc_rng_global_get_byte_fast(void)
+{
+#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(void)
{
return global_rng ? silc_rng_get_rn16(global_rng) : 0;
}
-uint32 silc_rng_global_get_rn32()
+uint32 silc_rng_global_get_rn32(void)
{
return global_rng ? silc_rng_get_rn32(global_rng) : 0;
}