.rng_name = "/dev/hw_random",
.rng_fd = -1,
.xread = xread,
- .fipsctx = NULL,
- .next = NULL,
};
static struct rng rng_tpm = {
.rng_name = "/dev/tpm0",
.rng_fd = -1,
.xread = xread_tpm,
- .fipsctx = NULL,
- .next = NULL,
};
struct rng *rng_list;
{
unsigned char buf[FIPS_RNG_BUFFER_SIZE];
int retval;
+ int no_work = 0;
- for (;;) {
+ while (no_work < 100) {
struct rng *iter;
+ bool work_done;
+
+ work_done = false;
for (iter = rng_list; iter; iter = iter->next)
{
+ int rc;
+
+ if (iter->disabled)
+ continue; /* failed, no work */
+
retval = iter->xread(buf, sizeof buf, iter);
- if (retval == 0)
- update_kernel_random(random_step,
- poll_timeout, buf,
- iter->fipsctx);
+ if (retval)
+ continue; /* failed, no work */
+
+ work_done = true;
+
+ rc = update_kernel_random(random_step,
+ poll_timeout, buf,
+ iter->fipsctx);
+ if (rc == 0)
+ continue; /* succeeded, work done */
+
+ iter->failures++;
+ if (iter->failures == MAX_RNG_FAILURES) {
+ message(LOG_DAEMON|LOG_ERR,
+ "too many FIPS failures, disabling entropy source\n");
+ iter->disabled = true;
+ }
}
+
+ if (!work_done)
+ no_work++;
}
+
+ message(LOG_DAEMON|LOG_ERR,
+ "No entropy sources working, exiting rngd\n");
}
int main(int argc, char **argv)
#include <unistd.h>
#include <stdint.h>
+#include <stdbool.h>
#include <stdio.h>
#include <syslog.h>
#include "fips.h"
+enum {
+ MAX_RNG_FAILURES = 25,
+};
+
/* Command line arguments and processing */
struct arguments {
char *random_name;
struct rng {
char *rng_name;
int rng_fd;
+ bool disabled;
+ int failures;
int (*xread) (void *buf, size_t size, struct rng *ent_src);
fips_ctx_t *fipsctx;