#define SILC_RNG_STATE_NUM 4
/* Byte size of the random data pool. */
-#define SILC_RNG_POOLSIZE 1024
+#define SILC_RNG_POOLSIZE (20 * 48)
-static uint32 silc_rng_get_position(SilcRng rng);
+static SilcUInt32 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_xor(SilcRng rng, SilcUInt32 val, unsigned int pos);
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);
from the same point of the pool. Short description of the fields
following.
- uint32 low
- uint32 pos
+ SilcUInt32 low
+ SilcUInt32 pos
The index for the random pool buffer. Lowest and current
positions.
*/
typedef struct SilcRngStateContext {
- uint32 low;
- uint32 pos;
+ SilcUInt32 low;
+ SilcUInt32 pos;
struct SilcRngStateContext *next;
} *SilcRngState;
random pool. This is allocated when RNG object is allocated and
free'd when RNG object is free'd.
- uint8 threshold
+ SilcUInt8 threshold
Threshold to indicate when it is required to acquire more
noise from the environment. More soft noise is acquired after
unsigned char key[64];
SilcRngState state;
SilcHash sha1;
- uint8 threshold;
+ SilcUInt8 threshold;
char *devrandom;
int fd_devurandom;
};
void silc_rng_free(SilcRng rng)
{
if (rng) {
+ SilcRngState t, n;
+
memset(rng->pool, 0, sizeof(rng->pool));
memset(rng->key, 0, sizeof(rng->key));
silc_hash_free(rng->sha1);
if (rng->fd_devurandom != -1)
close(rng->fd_devurandom);
+ for (t = rng->state->next; t != rng->state; ) {
+ n = t->next;
+ silc_free(t);
+ t = n;
+ }
+ silc_free(rng->state);
+
silc_free(rng);
}
}
#ifndef SILC_WIN32
struct tms ptime;
#endif
- uint32 pos;
+ SilcUInt32 pos;
pos = silc_rng_get_position(rng);
/* Get data as much as we can get into the buffer */
for (i = 0; i < sizeof(buf); i++) {
c = fgetc(fd);
- if (c == EOF) {
- if (!i)
- return;
+ if (c == EOF)
break;
- }
buf[i] = c;
}
pclose(fd);
- /* Add the buffer into random pool */
- silc_rng_add_noise(rng, buf, i);
- memset(buf, 0, sizeof(buf));
+ if (i != 0) {
+ /* Add the buffer into random pool */
+ 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
pool. After adding the noise the pool is stirred. */
-void silc_rng_add_noise(SilcRng rng, unsigned char *buffer, uint32 len)
+void silc_rng_add_noise(SilcRng rng, unsigned char *buffer, SilcUInt32 len)
{
- uint32 i, pos;
+ SilcUInt32 i, pos;
pos = silc_rng_get_position(rng);
/* XOR's data into the pool */
-static void silc_rng_xor(SilcRng rng, uint32 val, unsigned int pos)
+static void silc_rng_xor(SilcRng rng, SilcUInt32 val, unsigned int pos)
{
- assert(rng != NULL);
- rng->pool[pos] ^= val + val;
+ SilcUInt32 tmp;
+
+ SILC_GET32_MSB(tmp, &rng->pool[pos]);
+ val ^= tmp + val;
+ SILC_PUT32_MSB(val, &rng->pool[pos]);
}
/* This function stirs the random pool by encrypting buffer in CFB
static void silc_rng_stir_pool(SilcRng rng)
{
int i;
- uint32 iv[5];
+ SilcUInt32 iv[5], tmp;
/* Get the IV */
- memcpy(iv, &rng->pool[16], sizeof(iv));
+ SILC_GET32_MSB(iv[0], &rng->pool[16 ]);
+ SILC_GET32_MSB(iv[1], &rng->pool[16 + 4]);
+ SILC_GET32_MSB(iv[2], &rng->pool[16 + 8]);
+ SILC_GET32_MSB(iv[3], &rng->pool[16 + 12]);
+ SILC_GET32_MSB(iv[4], &rng->pool[16 + 16]);
/* First CFB pass */
- for (i = 0; i < SILC_RNG_POOLSIZE; i += 5) {
- rng->sha1->hash->transform(iv, rng->key);
- iv[0] = rng->pool[i] ^= iv[0];
- iv[1] = rng->pool[i + 1] ^= iv[1];
- iv[2] = rng->pool[i + 2] ^= iv[2];
- iv[3] = rng->pool[i + 3] ^= iv[3];
- iv[4] = rng->pool[i + 4] ^= iv[4];
+ for (i = 0; i < SILC_RNG_POOLSIZE; i += 20) {
+ silc_hash_transform(rng->sha1, iv, rng->key);
+
+ SILC_GET32_MSB(tmp, &rng->pool[i]);
+ iv[0] ^= tmp;
+ SILC_PUT32_MSB(iv[0], &rng->pool[i]);
+
+ SILC_GET32_MSB(tmp, &rng->pool[i + 4]);
+ iv[1] ^= tmp;
+ SILC_PUT32_MSB(iv[1], &rng->pool[i + 4]);
+
+ SILC_GET32_MSB(tmp, &rng->pool[i + 8]);
+ iv[2] ^= tmp;
+ SILC_PUT32_MSB(iv[2], &rng->pool[i + 8]);
+
+ SILC_GET32_MSB(tmp, &rng->pool[i + 12]);
+ iv[3] ^= tmp;
+ SILC_PUT32_MSB(iv[3], &rng->pool[i + 12]);
+
+ SILC_GET32_MSB(tmp, &rng->pool[i + 16]);
+ iv[4] ^= tmp;
+ SILC_PUT32_MSB(iv[4], &rng->pool[i + 16]);
}
/* Get new key */
memcpy(rng->key, &rng->pool[silc_rng_get_position(rng)], sizeof(rng->key));
/* Second CFB pass */
- for (i = 0; i < SILC_RNG_POOLSIZE; i += 5) {
- rng->sha1->hash->transform(iv, rng->key);
- iv[0] = rng->pool[i] ^= iv[0];
- iv[1] = rng->pool[i + 1] ^= iv[1];
- iv[2] = rng->pool[i + 2] ^= iv[2];
- iv[3] = rng->pool[i + 3] ^= iv[3];
- iv[4] = rng->pool[i + 4] ^= iv[4];
+ for (i = 0; i < SILC_RNG_POOLSIZE; i += 20) {
+ silc_hash_transform(rng->sha1, iv, rng->key);
+
+ SILC_GET32_MSB(tmp, &rng->pool[i]);
+ iv[0] ^= tmp;
+ SILC_PUT32_MSB(iv[0], &rng->pool[i]);
+
+ SILC_GET32_MSB(tmp, &rng->pool[i + 4]);
+ iv[1] ^= tmp;
+ SILC_PUT32_MSB(iv[1], &rng->pool[i + 4]);
+
+ SILC_GET32_MSB(tmp, &rng->pool[i + 8]);
+ iv[2] ^= tmp;
+ SILC_PUT32_MSB(iv[2], &rng->pool[i + 8]);
+
+ SILC_GET32_MSB(tmp, &rng->pool[i + 12]);
+ iv[3] ^= tmp;
+ SILC_PUT32_MSB(iv[3], &rng->pool[i + 12]);
+
+ SILC_GET32_MSB(tmp, &rng->pool[i + 16]);
+ iv[4] ^= tmp;
+ SILC_PUT32_MSB(iv[4], &rng->pool[i + 16]);
}
memset(iv, 0, sizeof(iv));
/* Returns next position where data is fetched from the pool or
put to the pool. */
-static uint32 silc_rng_get_position(SilcRng rng)
+static SilcUInt32 silc_rng_get_position(SilcRng rng)
{
SilcRngState next;
- uint32 pos;
+ SilcUInt32 pos;
next = rng->state->next;
/* Returns random byte. */
-uint8 silc_rng_get_byte(SilcRng rng)
+SilcUInt8 silc_rng_get_byte(SilcRng rng)
{
rng->threshold++;
return rng->pool[silc_rng_get_position(rng)];
}
+/* Return random byte as fast as possible. Reads from /dev/urandom if
+ available. If not then return from normal RNG (not so fast). */
+
+SilcUInt8 silc_rng_get_byte_fast(SilcRng rng)
+{
+#ifndef SILC_WIN32
+ unsigned char buf[1];
+
+ if (rng->fd_devurandom == -1) {
+ rng->fd_devurandom = open("/dev/urandom", O_RDONLY);
+ if (rng->fd_devurandom < 0)
+ return silc_rng_get_byte(rng);
+ fcntl(rng->fd_devurandom, F_SETFL, O_NONBLOCK);
+ }
+
+ if (read(rng->fd_devurandom, buf, sizeof(buf)) < 0)
+ return silc_rng_get_byte(rng);
+
+ return buf[0];
+#else
+ return silc_rng_get_byte(rng);
+#endif
+}
+
/* Returns 16 bit random number */
-uint16 silc_rng_get_rn16(SilcRng rng)
+SilcUInt16 silc_rng_get_rn16(SilcRng rng)
{
unsigned char rn[2];
- uint16 num;
+ SilcUInt16 num;
rn[0] = silc_rng_get_byte(rng);
rn[1] = silc_rng_get_byte(rng);
/* Returns 32 bit random number */
-uint32 silc_rng_get_rn32(SilcRng rng)
+SilcUInt32 silc_rng_get_rn32(SilcRng rng)
{
unsigned char rn[4];
- uint16 num;
+ SilcUInt32 num;
rn[0] = silc_rng_get_byte(rng);
rn[1] = silc_rng_get_byte(rng);
/* Returns random number string. Returned string is in HEX format. */
-unsigned char *silc_rng_get_rn_string(SilcRng rng, uint32 len)
+unsigned char *silc_rng_get_rn_string(SilcRng rng, SilcUInt32 len)
{
int i;
unsigned char *string;
/* Returns random number binary data. */
-unsigned char *silc_rng_get_rn_data(SilcRng rng, uint32 len)
+unsigned char *silc_rng_get_rn_data(SilcRng rng, SilcUInt32 len)
{
int i;
unsigned char *data;
/* These are analogous to the functions above. */
-uint8 silc_rng_global_get_byte(void)
+SilcUInt8 silc_rng_global_get_byte(void)
{
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). */
-uint8 silc_rng_global_get_byte_fast(void)
+SilcUInt8 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
+ return global_rng ? silc_rng_get_byte_fast(global_rng) : 0;
}
-uint16 silc_rng_global_get_rn16(void)
+SilcUInt16 silc_rng_global_get_rn16(void)
{
return global_rng ? silc_rng_get_rn16(global_rng) : 0;
}
-uint32 silc_rng_global_get_rn32(void)
+SilcUInt32 silc_rng_global_get_rn32(void)
{
return global_rng ? silc_rng_get_rn32(global_rng) : 0;
}
-unsigned char *silc_rng_global_get_rn_string(uint32 len)
+unsigned char *silc_rng_global_get_rn_string(SilcUInt32 len)
{
return global_rng ? silc_rng_get_rn_string(global_rng, len) : NULL;
}
-unsigned char *silc_rng_global_get_rn_data(uint32 len)
+unsigned char *silc_rng_global_get_rn_data(SilcUInt32 len)
{
return global_rng ? silc_rng_get_rn_data(global_rng, len) : NULL;
}
-void silc_rng_global_add_noise(unsigned char *buffer, uint32 len)
+void silc_rng_global_add_noise(unsigned char *buffer, SilcUInt32 len)
{
if (global_rng)
silc_rng_add_noise(global_rng, buffer, len);