#ifdef HAVE_RANDOM
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#endif
#include "tinydtls.h"
#include "dtls_prng.h"
#include "dtls_debug.h"
#ifdef HAVE_GETRANDOM
#include <sys/random.h>
#endif
#include <stdlib.h>
#include <stdio.h>
int
dtls_prng(unsigned char *buf, size_t len) {
#ifdef HAVE_GETRANDOM
return getrandom(buf, len, 0);
#elif defined(HAVE_RANDOM)
#define RAND_BYTES (RAND_MAX >= 0xffffff ? 3 : (RAND_MAX >= 0xffff ? 2 : 1))
if (len) {
size_t klen = len;
uint8_t byte_counter = RAND_BYTES;
uint32_t rand_val = random();
while (1) {
*buf++ = rand_val & 0xFF;
if (!--klen) {
break;
}
if (--byte_counter) {
rand_val >>= 8;
} else {
rand_val = random();
byte_counter = RAND_BYTES;
}
}
}
return len;
#else
#error "CVE-2021-34430: using rand() for crypto randoms is not secure!"
#error "Please update you C-library and rerun the auto-configuration."
size_t klen = len;
while (len--)
*buf++ = rand() & 0xFF;
return klen;
#endif
}
void
dtls_prng_init(unsigned seed) {
#ifdef HAVE_GETRANDOM
(void)seed;
#else
FILE *urandom = fopen("/dev/urandom", "r");
unsigned char buf[sizeof(unsigned long)];
(void)seed;
if (!urandom) {
dtls_emerg("cannot initialize PRNG\n");
return;
}
if (fread(buf, 1, sizeof(buf), urandom) != sizeof(buf)) {
dtls_emerg("cannot initialize PRNG\n");
return;
}
fclose(urandom);
#ifdef HAVE_RANDOM
srandom((unsigned long)*buf);
#else
srand((unsigned long)*buf);
#endif
#endif
}