#ifndef UTIL_LINUX_RANDUTILS
#define UTIL_LINUX_RANDUTILS
+/* command flags */
+typedef enum {
+ UL_RAND_WEAK = 0, /* computed with libc functionality */
+ UL_RAND_GETRANDOM, /* retrieved from getrandom(2) */
+ UL_RAND_RANDOM, /* read from /dev/random */
+ UL_RAND_URANDOM /* read from /dev/urandom */
+} ul_random_src_t;
+
/* getrandom(2) based with fallback to /dev/(u)random and libc randomness */
-extern int ul_random_get_bytes(void *buf, size_t nbytes);
-extern const char *random_tell_source(void);
+extern ul_random_src_t ul_random_get_bytes(void *buf, size_t nbytes);
+extern const char *ul_random_tell_source(ul_random_src_t);
#endif
rand();
}
-static int random_get_fd(void)
+static int random_get_fd(ul_random_src_t *src)
{
int fd;
+ *src = UL_RAND_URANDOM;
fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC);
- if (fd == -1)
+ if (fd == -1) {
+ *src = UL_RAND_RANDOM;
fd = open("/dev/random", O_RDONLY | O_NONBLOCK | O_CLOEXEC);
+ }
crank_random();
return fd;
}
/*
* Write @nbytes random bytes into @buf.
*
- * Returns 0 for good quality of random bytes or 1 for weak quality.
+ * Returns source of random bytes (0 for weak quality).
*/
-int ul_random_get_bytes(void *buf, size_t nbytes)
+ul_random_src_t ul_random_get_bytes(void *buf, size_t nbytes)
{
unsigned char *cp = (unsigned char *)buf;
size_t i, n = nbytes;
+ ul_random_src_t src;
int lose_counter = 0;
#ifdef HAVE_GETRANDOM
} else
break;
}
+ if (n == 0)
+ return UL_RAND_GETRANDOM;
if (errno == ENOSYS)
#endif
* as before
*/
{
- int fd = random_get_fd();
+ int fd = random_get_fd(&src);
lose_counter = 0;
if (fd >= 0) {
close(fd);
}
+ if (n == 0)
+ return src;
}
/*
* We do this all the time, but this is the only source of
}
#endif
- return n != 0;
+ return UL_RAND_WEAK;
}
/*
* Tell source of randomness.
*/
-const char *random_tell_source(void)
+const char *ul_random_tell_source(ul_random_src_t src)
{
-#ifdef HAVE_GETRANDOM
- return _("getrandom() function");
-#else
- size_t i;
- static const char *const random_sources[] = {
- "/dev/urandom",
- "/dev/random"
- };
-
- for (i = 0; i < ARRAY_SIZE(random_sources); i++) {
- if (!access(random_sources[i], R_OK))
- return random_sources[i];
+ const char *s;
+
+ switch (src) {
+ case UL_RAND_GETRANDOM:
+ s = _("getrandom() function");
+ break;
+ case UL_RAND_RANDOM:
+ s = "/dev/random";
+ break;
+ case UL_RAND_URANDOM:
+ s = "/dev/urandom";
+ break;
+ default:
+ s = _("libc pseudo-random functions");
+ break;
}
-#endif
- return _("libc pseudo-random functions");
+
+ return s;
}
#ifdef TEST_PROGRAM_RANDUTILS
n = *num;
for (i = 0; i < n; i++) {
- if (ul_random_get_bytes(buf, sizeof(buf)))
+ if (ul_random_get_bytes(buf, sizeof(buf)) == UL_RAND_WEAK)
r = -1;
uuid_unpack(buf, &uu);
unsigned char digest[UL_MD5LENGTH];
unsigned char buf[RAND_BYTES];
int c;
+ ul_random_src_t src;
static const struct option longopts[] = {
{"file", required_argument, NULL, 'f'},
randomness_from_files(&ctl);
free(ctl.files);
- ul_random_get_bytes(&buf, RAND_BYTES);
+ src = ul_random_get_bytes(&buf, RAND_BYTES);
ul_MD5Update(&ctl.ctx, buf, RAND_BYTES);
if (ctl.verbose)
fprintf(stderr, P_("Got %d byte from %s\n",
"Got %d bytes from %s\n", RAND_BYTES),
- RAND_BYTES, random_tell_source());
+ RAND_BYTES, ul_random_tell_source(src));
ul_MD5Final(digest, &ctl.ctx);
for (i = 0; i < UL_MD5LENGTH; i++)