rngd : random number generator daemon
Bernhard Fischer
rep.dot.nop at gmail.com
Mon Aug 18 15:15:14 UTC 2008
On Sun, Aug 17, 2008 at 09:07:32PM +0000, Malek wrote:
> Tito a écrit :
>> On Sunday 17 August 2008 16:55:16 Malek wrote:
>>> This new applet adds the rngd daemon to Busybox like rng-tools
>>>
>>> Thanks
>>>
>>> Malek
>>>
>>
>> Hi,
>> please fix ioctl_or_perror_and_die as strerror(errno) and \n are not needed.
>>
>> - ioctl_or_perror_and_die(random_fd, RNDADDENTROPY, entropy, "RNDADDENTROPY failed: %s\n",
>> - strerror(errno));
>> + ioctl_or_perror_and_die(random_fd, RNDADDENTROPY, entropy, "RNDADDENTROPY failed: %s");
>>
>> - ioctl_or_perror_and_die(random_fd, RNDGETENTCNT, &ent_count, "RNDGETENTCNT failed: %s\n",
>> - strerror(errno));
>> + ioctl_or_perror_and_die(random_fd, RNDGETENTCNT, &ent_count, "RNDGETENTCNT failed: %s");
>>
>>
>> Ciao,
>> Tito
>>
> Ok, done
>
> Denys Vlasenko a écrit :
> > On Sunday 17 August 2008 16:55, Malek wrote:
> >> This new applet adds the rngd daemon to Busybox like rng-tools
> >
> > Can you get rid of rng_fips.h and move its contents into rngd.c?
>
> done
>
> > Otherwise, it looks ok.
> >
> > Did you create this patch because you needed it for some project?
>
> not specially
>
> >
> > Which version of rngd it is based on?
>
> It based on rng-tools 2
>
> > How much of "standard" functionality it implements?
>
> It implements all functionalities of the original rngd
>
> > Can you write a comment describing this?
> > --
> > vda
> done in Config.in
>
> Thanks
>
> Malek
>diff -U 3 -H -d -p -r -N -- busybox.orig/include/applets.h busybox/include/applets.h
>--- busybox.orig/include/applets.h 2008-08-17 07:20:15.000000000 +0000
>+++ busybox/include/applets.h 2008-08-17 12:13:47.000000000 +0000
>@@ -298,6 +298,7 @@ USE_RESTORECON(APPLET_ODDNAME(restorecon
> USE_RM(APPLET_NOFORK(rm, rm, _BB_DIR_BIN, _BB_SUID_NEVER, rm))
> USE_RMDIR(APPLET_NOFORK(rmdir, rmdir, _BB_DIR_BIN, _BB_SUID_NEVER, rmdir))
> USE_RMMOD(APPLET(rmmod, _BB_DIR_SBIN, _BB_SUID_NEVER))
>+USE_RNGD(APPLET(rngd, _BB_DIR_USR_SBIN, _BB_SUID_NEVER))
> USE_MODPROBE_SMALL(APPLET_ODDNAME(rmmod, modprobe, _BB_DIR_SBIN, _BB_SUID_NEVER, modprobe))
> USE_ROUTE(APPLET(route, _BB_DIR_SBIN, _BB_SUID_NEVER))
> USE_RPM(APPLET(rpm, _BB_DIR_BIN, _BB_SUID_NEVER))
>diff -U 3 -H -d -p -r -N -- busybox.orig/include/usage.h busybox/include/usage.h
>--- busybox.orig/include/usage.h 2008-08-17 07:20:15.000000000 +0000
>+++ busybox/include/usage.h 2008-08-17 12:14:54.000000000 +0000
>@@ -3277,6 +3277,42 @@
> #define rmmod_example_usage \
> "$ rmmod tulip\n"
>
>+#define rngd_trivial_usage \
>+ "[-bf] [-o random file] [-r rng file] [-s step] [-t nnn] [-W n]"
>+#define rngd_full_usage "\n\n" \
>+ "Check and feed random data from hardware device to kernel entropy pool.\n" \
>+ "\nOptions:" \
>+ USE_FEATURE_RNGD_LONG_OPTIONS( \
>+ "\n -b,--background Become a daemon (default)" \
>+ "\n -f,--foreground Do not fork and become a daemon" \
>+ "\n -o,--rng-device=file Kernel device used for random number output" \
>+ "\n (default: /dev/random)" \
>+ "\n -r,--random-step=nnn Kernel device used for random number input" \
>+ "\n (default: /dev/hw_random)" \
>+ "\n -s,--random-step=nnn Number of bytes written to random-device at a time" \
>+ "\n (default: 64)" \
>+ "\n -t,--timeout=nnn Interval written to random-device when the entropy" \
>+ "\n pool is full, in seconds (default: 60)" \
>+ "\n -W,--fill-watermark=n Do not stop feeding entropy to random-device until" \
>+ "\n at least n bits of entropy are available in the" \
>+ "\n pool (default: 2048), 0 <= n <= 4096" \
>+ ) \
>+ SKIP_FEATURE_RNGD_LONG_OPTIONS( \
>+ "\n -b Become a daemon (default)" \
>+ "\n -f Do not fork and become a daemon" \
>+ "\n -o Kernel device used for random number output" \
>+ "\n (default: /dev/random)" \
>+ "\n -r Kernel device used for random number input" \
>+ "\n (default: /dev/hw_random)" \
>+ "\n -s Number of bytes written to random-device at a time" \
>+ "\n (default: 64)" \
>+ "\n -t Interval written to random-device when the entropy" \
>+ "\n pool is full, in seconds (default: 60)" \
>+ "\n -W Do not stop feeding entropy to random-device until" \
>+ "\n at least n bits of entropy are available in the" \
>+ "\n pool (default: 2048), 0 <= n <= 4096" \
>+ )
>+
> #define route_trivial_usage \
> "[{add|del|delete}]"
> #define route_full_usage "\n\n" \
>diff -U 3 -H -d -p -r -N -- busybox.orig/miscutils/Config.in busybox/miscutils/Config.in
>--- busybox.orig/miscutils/Config.in 2008-08-17 07:20:15.000000000 +0000
>+++ busybox/miscutils/Config.in 2008-08-17 20:50:42.000000000 +0000
>@@ -448,6 +448,23 @@ config READAHEAD
> As readahead(2) blocks until each file has been read, it is best to
> run this applet as a background job.
>
>+config RNGD
>+ bool "rngd"
>+ default n
>+ help
>+ Hardware random number generation daemon.
>+
>+ rngd is a daemon that feeds data from a hardware random number
>+ generator to the kernel's random number entropy pool. it improves
>+ the functioning of sshd/dropbear, stunnel...
>+
>+config FEATURE_RNGD_LONG_OPTIONS
>+ bool "Enable long options"
>+ default n
>+ depends on RNGD && GETOPT_LONG
>+ help
>+ Support long options for the rngd applet.
>+
> config RUNLEVEL
> bool "runlevel"
> default n
>diff -U 3 -H -d -p -r -N -- busybox.orig/miscutils/Kbuild busybox/miscutils/Kbuild
>--- busybox.orig/miscutils/Kbuild 2008-08-17 07:20:15.000000000 +0000
>+++ busybox/miscutils/Kbuild 2008-08-17 12:12:24.000000000 +0000
>@@ -27,6 +27,7 @@ lib-$(CONFIG_MOUNTPOINT) += mountpoint.
> lib-$(CONFIG_MT) += mt.o
> lib-$(CONFIG_RAIDAUTORUN) += raidautorun.o
> lib-$(CONFIG_READAHEAD) += readahead.o
>+lib-$(CONFIG_RNGD) += rngd.o
> lib-$(CONFIG_RUNLEVEL) += runlevel.o
> lib-$(CONFIG_RX) += rx.o
> lib-$(CONFIG_SETSID) += setsid.o
>diff -U 3 -H -d -p -r -N -- busybox.orig/miscutils/rngd.c busybox/miscutils/rngd.c
>--- busybox.orig/miscutils/rngd.c 1970-01-01 00:00:00.000000000 +0000
>+++ busybox/miscutils/rngd.c 2008-08-17 20:17:00.000000000 +0000
>@@ -0,0 +1,297 @@
>+/* vi: set sw=4 ts=4: */
>+/*
>+ * rngd implementation for busybox
>+ *
>+ * The original version was writen by Philipp Rumpf
s/writen/written/g
>+ *
>+ * Ported to busybox by Malek Degachi
>+ *
>+ * Licensed under GPLv2 or later, see file License in this tarball for details.
>+ *
>+ */
>+
>+#include "libbb.h"
>+#include <syslog.h>
>+
>+#ifndef __u32
>+typedef unsigned int __u32;
>+#endif
__u32 comes from include/platform.h or from the compiler and as such
must not be defined here. Please remove it.
>+#include <linux/random.h> /* struct rand_pool_info, RNDADDENTROPY and RNDGETENTCNT */
>+
>+/**********************************************
>+ * FIPS part
>+ *********************************************/
>+
>+/* Size of a FIPS test buffer, do not change this */
>+#define FIPS_RNG_BUFFER_SIZE 2500
>+
>+/* Context for running FIPS tests */
>+typedef struct {
>+ int poker[16];
>+ int runs[12];
>+ int ones;
>+ int rlength;
>+ int current_bit;
>+ int last_bit;
>+ int longrun;
>+ unsigned int last32;
>+} fips_ctx_t;
>+
>+/*
>+ * Return values for fips_run_rng_test. These values are OR'ed together
>+ * for all tests that failed.
>+ */
>+#define FIPS_RNG_MONOBIT 0x0001 /* FIPS 140-2 2001-10-10 monobit */
>+#define FIPS_RNG_POKER 0x0002 /* FIPS 140-2 2001-10-10 poker */
>+#define FIPS_RNG_RUNS 0x0004 /* FIPS 140-2 2001-10-10 runs */
>+#define FIPS_RNG_LONGRUN 0x0008 /* FIPS 140-2 2001-10-10 long run */
>+#define FIPS_RNG_CONTINUOUS_RUN 0x0010 /* FIPS 140-2 continuous run */
>+
>+/*
>+ * fips_test_store - store 8 bits of entropy in FIPS
>+ * internal test data pool
>+ */
>+static void fips_test_store(fips_ctx_t *ctx, unsigned int rng_data)
>+{
>+ int j;
>+
>+ ctx->poker[rng_data >> 4]++;
>+ ctx->poker[rng_data & 15]++;
>+
>+ /* Note in the loop below rlength is always one less than the actual
>+ run length. This makes things easier. */
>+ for (j = 7; j >= 0; j--) {
>+ ctx->ones += ctx->current_bit = ((rng_data >> j) & 1);
>+ if (ctx->current_bit != ctx->last_bit) {
>+ /* If runlength is 1-6 count it in correct bucket. 0's go in
>+ runs[0-5] 1's go in runs[6-11] hence the 6*current_bit below */
>+ if (ctx->rlength < 5) {
>+ ctx->runs[ctx->rlength +
>+ (6 * ctx->current_bit)]++;
>+ } else {
>+ ctx->runs[5 + (6 * ctx->current_bit)]++;
>+ }
>+
>+ /* Check if we just failed longrun test */
>+ if (ctx->rlength >= 25)
>+ ctx->longrun = 1;
>+ ctx->rlength = 0;
>+ /* flip the current run type */
>+ ctx->last_bit = ctx->current_bit;
>+ } else {
>+ ctx->rlength++;
>+ }
>+ }
>+}
>+
>+static int fips_run_rng_test(fips_ctx_t *ctx, const void *buf)
>+{
>+ int i, j;
>+ int rng_test = 0;
>+ unsigned char *rngdatabuf;
>+
>+ if (!ctx) return -1;
>+ if (!buf) return -1;
>+ rngdatabuf = (unsigned char *)buf;
>+
>+ for (i=0; i<FIPS_RNG_BUFFER_SIZE; i += 4) {
>+ int new32 = rngdatabuf[i] |
>+ ( rngdatabuf[i+1] << 8 ) |
>+ ( rngdatabuf[i+2] << 16 ) |
above 3 lines contain whitespace damage.
>+ ( rngdatabuf[i+3] << 24 );
>+ if (new32 == ctx->last32) rng_test |= FIPS_RNG_CONTINUOUS_RUN;
>+ ctx->last32 = new32;
>+ fips_test_store(ctx, rngdatabuf[i]);
>+ fips_test_store(ctx, rngdatabuf[i+1]);
>+ fips_test_store(ctx, rngdatabuf[i+2]);
>+ fips_test_store(ctx, rngdatabuf[i+3]);
>+ }
>+
>+ /* add in the last (possibly incomplete) run */
>+ if (ctx->rlength < 5)
>+ ctx->runs[ctx->rlength + (6 * ctx->current_bit)]++;
>+ else {
>+ ctx->runs[5 + (6 * ctx->current_bit)]++;
>+ if (ctx->rlength >= 25)
>+ rng_test |= FIPS_RNG_LONGRUN;
>+ }
>+
whitespace damage in the above line.
>+ if (ctx->longrun) {
>+ rng_test |= FIPS_RNG_LONGRUN;
>+ ctx->longrun = 0;
>+ }
>+
>+ /* Ones test */
>+ if ((ctx->ones >= 10275) || (ctx->ones <= 9725))
>+ rng_test |= FIPS_RNG_MONOBIT;
>+ /* Poker calcs */
>+ for (i = 0, j = 0; i < 16; i++)
>+ j += ctx->poker[i] * ctx->poker[i];
>+ /* 16/5000*1563176-5000 = 2.1632 */
>+ /* 16/5000*1576928-5000 = 46.1696 */
>+ if ((j > 1576928) || (j < 1563176))
>+ rng_test |= FIPS_RNG_POKER;
>+
>+ if ((ctx->runs[0] < 2315) || (ctx->runs[0] > 2685) ||
>+ (ctx->runs[1] < 1114) || (ctx->runs[1] > 1386) ||
>+ (ctx->runs[2] < 527) || (ctx->runs[2] > 723) ||
>+ (ctx->runs[3] < 240) || (ctx->runs[3] > 384) ||
>+ (ctx->runs[4] < 103) || (ctx->runs[4] > 209) ||
>+ (ctx->runs[5] < 103) || (ctx->runs[5] > 209) ||
>+ (ctx->runs[6] < 2315) || (ctx->runs[6] > 2685) ||
>+ (ctx->runs[7] < 1114) || (ctx->runs[7] > 1386) ||
>+ (ctx->runs[8] < 527) || (ctx->runs[8] > 723) ||
>+ (ctx->runs[9] < 240) || (ctx->runs[9] > 384) ||
>+ (ctx->runs[10] < 103) || (ctx->runs[10] > 209) ||
>+ (ctx->runs[11] < 103) || (ctx->runs[11] > 209)) {
>+ rng_test |= FIPS_RNG_RUNS;
>+ }
>+
whitespace damage in the above line.
>+ /* finally, clear out FIPS variables for start of next run */
>+ memset(ctx->poker, 0, sizeof (ctx->poker));
>+ memset(ctx->runs, 0, sizeof (ctx->runs));
>+ ctx->ones = 0;
>+ ctx->rlength = -1;
>+ ctx->current_bit = 0;
>+
>+ return rng_test;
>+}
>+/**********************************************
>+ * End of FIPS part
>+ *********************************************/
>+
>+enum {
>+ RNG_b = (1 << 0),
>+ RNG_f = (1 << 1),
>+ RNG_o = (1 << 2),
>+ RNG_r = (1 << 3),
>+ RNG_s = (1 << 4),
>+ RNG_t = (1 << 5),
>+ RNG_W = (1 << 6),
No need for that ',' in the line above.
>+};
>+
>+static void random_add_entropy(int random_fd, void *buf, size_t size)
>+{
>+ struct rand_pool_info *entropy;
>+
>+ entropy = xmalloc(sizeof(struct rand_pool_info) + size);
>+
>+ entropy->entropy_count = size * 8;
>+ entropy->buf_size = size;
>+ memcpy(entropy->buf, buf, size);
>+
>+ ioctl_or_perror_and_die(random_fd, RNDADDENTROPY, entropy, "RNDADDENTROPY failed");
This ignores our setting that controls whether or not to print IOCTL
names. Please fix.
>+}
>+
>+static void random_sleep(int random_fd, double timeout, unsigned fill_watermark)
>+{
>+ int ent_count;
>+ struct pollfd pfd[1];
>+
>+ pfd[0].fd = random_fd;
>+ pfd[0].events = POLLOUT;
>+
>+ ioctl_or_perror_and_die(random_fd, RNDGETENTCNT, &ent_count, "RNDGETENTCNT failed");
ditto
>+ if (ent_count < fill_watermark) return;
>+
whitespace damage in the above line.
>+ safe_poll(pfd, 1, 1000.0 * timeout);
>+}
Is it smaller to fold both random_add_entropy() and random_sleep() into
their only user?
>+
>+/* Initialize entropy source */
>+static int discard_initial_data(int rng_fd)
>+{
>+ /* Trash 32 bits of what is probably stale (non-random)
>+ * initial state from the RNG. For Intel's, 8 bits would
>+ * be enough, but since AMD's generates 32 bits at a time...
>+ *
>+ * The kernel drivers should be doing this at device powerup,
>+ * but at least up to 2.4.24, it doesn't. */
>+ unsigned char tempbuf[4];
>+
>+ xread(rng_fd, tempbuf, sizeof tempbuf);
>+
>+ /* Return 32 bits of bootstrap data */
>+ xread(rng_fd, tempbuf, sizeof tempbuf);
>+
>+ return tempbuf[0] | (tempbuf[1] << 8) |
whitespace damage in the above line.
>+ (tempbuf[2] << 16) | (tempbuf[3] << 24);
>+}
>+
>+
>+#if ENABLE_FEATURE_RNGD_LONG_OPTIONS
>+static const char rngd_longopts[] ALIGN1 =
>+ "background\0" No_argument "b"
>+ "foreground\0" No_argument "f"
>+ "random-device\0" Required_argument "o"
>+ "rng-device\0" Required_argument "r"
>+ "random-step\0" Required_argument "s"
>+ "timeout\0" Required_argument "t"
>+ "fill-watermark\0" Required_argument "W"
>+ ;
>+#endif
>+
>+int rngd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
>+int rngd_main(int argc UNUSED_PARAM, char **argv)
>+{
>+ const char *random_name = "/dev/random";
>+ const char *rng_name = "/dev/hw_random";
I think we have something like device_open() which prepends "/dev/" for
you.
>+ int random_step = 64;
>+ unsigned fill_watermark;
>+ double poll_timeout = 60;
Eh, a double is a bit heavy, can we get away with unsigned long ?
>+
>+ const char *watermark = "2048";
>+ static int rng_fd;
>+ static int random_fd;
>+
>+ unsigned char buf[FIPS_RNG_BUFFER_SIZE];
>+ unsigned char *p;
>+ int fips;
unneeded variable "fips". Please remove it.
>+ fips_ctx_t *fipsctx;
>+
>+#if ENABLE_FEATURE_RNGD_LONG_OPTIONS
>+ applet_long_options = rngd_longopts;
>+#endif
>+
>+ opt_complementary = "s+:t+";
>+ getopt32(argv, "bfo:r:s:t:W:", &random_name, &rng_name, &random_step, &poll_timeout, &watermark);
>+ argv += optind;
>+
>+ fill_watermark = xatou_range(watermark, 0, 4096);
>+
>+ /* Init entropy source, and open hardware RNG device */
>+ rng_fd = xopen(rng_name, O_RDONLY);
>+
>+ /* Bootstrap FIPS tests */
>+ fipsctx = (fips_ctx_t *) xzalloc(sizeof(fips_ctx_t));
>+ fipsctx->rlength = -1;
>+ fipsctx->last32 = discard_initial_data(rng_fd);
>+
>+ /* Init entropy sink and open random device */
>+ random_fd = xopen(random_name, O_RDWR);
>+
>+ if (!(option_mask32 & RNG_f)) { /* no -f */
>+ bb_daemonize_or_rexec(DAEMON_CHDIR_ROOT, argv);
>+ openlog(applet_name, LOG_PID, LOG_DAEMON);
>+ logmode = LOGMODE_SYSLOG;
>+ }
>+
>+ write_pidfile("/var/run/rngd.pid");
>+ for (;;) {
>+ xread(rng_fd, buf, sizeof buf);
>+
>+ fips = fips_run_rng_test(fipsctx, buf);
>+
>+ if (fips) {
>+ bb_info_msg("failed fips test");
>+ sleep(1);
>+ continue;
>+ }
>+
>+ for (p = buf; p + random_step <= &buf[sizeof buf]; p += random_step) {
>+ random_add_entropy(random_fd, p, random_step);
>+ random_sleep(random_fd, poll_timeout ? : -1.0, fill_watermark);
>+ }
>+ }
>+
>+ return EXIT_SUCCESS;
>+}
Please provide size(1) output for this applet.
TIA,
Bernhard
More information about the busybox
mailing list