Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package rng-tools for openSUSE:Factory checked in at 2021-01-25 18:23:36 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/rng-tools (Old) and /work/SRC/openSUSE:Factory/.rng-tools.new.28504 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "rng-tools" Mon Jan 25 18:23:36 2021 rev:45 rq:866173 version:6.11 Changes: -------- --- /work/SRC/openSUSE:Factory/rng-tools/rng-tools.changes 2020-09-14 12:30:36.277185746 +0200 +++ /work/SRC/openSUSE:Factory/.rng-tools.new.28504/rng-tools.changes 2021-01-25 18:23:54.428453651 +0100 @@ -1,0 +2,20 @@ +Sat Jan 23 00:29:32 UTC 2021 - Dirk M??ller <dmuel...@suse.com> + +- update to 6.11: + * Some CI/CD fixes in travis pipeline + * Fix detection of duplicate pulses in nist source + * Fix --with-rtlsdr option in configure + * Clean up some debug statements that were erroneously left in place + * Fix error in systemd unit file + * Fix buffer overflow in rtlsdr entropy source + * Fixed darn source rekeying + * Fix various pipe read issues in jitter source + * Fix listing of rtlsdr options + * Misc Documentation fixes + * Fix a broken FIPS 140-2 corner case test + * Misc cleanups + * Addd aes mangling to nist source + * Improve nist performance with opportunistic use of CLOCK_MONOTONIC_COARSE + * Add forced reseeding of kernel entropy pool + +------------------------------------------------------------------- Old: ---- v6.10.tar.gz New: ---- v6.11.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ rng-tools.spec ++++++ --- /var/tmp/diff_new_pack.JyrtWH/_old 2021-01-25 18:23:55.396455059 +0100 +++ /var/tmp/diff_new_pack.JyrtWH/_new 2021-01-25 18:23:55.400455064 +0100 @@ -1,7 +1,7 @@ # # spec file for package rng-tools # -# Copyright (c) 2020 SUSE LLC +# Copyright (c) 2021 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -18,7 +18,7 @@ %{!?_udevrulesdir: %global _udevrulesdir %(pkg-config --variable=udevdir udev)/rules.d } Name: rng-tools -Version: 6.10 +Version: 6.11 Release: 0 Summary: Support daemon for hardware random device License: GPL-3.0-or-later ++++++ v6.10.tar.gz -> v6.11.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rng-tools-6.10/.travis.yml new/rng-tools-6.11/.travis.yml --- old/rng-tools-6.10/.travis.yml 2020-03-27 17:52:27.000000000 +0100 +++ new/rng-tools-6.11/.travis.yml 2021-01-08 15:06:59.000000000 +0100 @@ -4,6 +4,8 @@ arch: - amd64 - arm64 + - ppc64le + - s390x compiler: - clang @@ -20,9 +22,13 @@ libp11-dev librtlsdr-dev libusb-1.0-0-dev + libjansson-dev - -script: rm -rf ./jitterentropy-library/* && ./autogen.sh && ./configure && make - -after_script: - - make check || (cat tests/rngtesturandom.sh.log && cat tests/rngtestzero.sh.log && cat ./tests/test-suite.log) +script: + - rm -rf ./jitterentropy-library/* + - ./autogen.sh + - ./configure + - make + - make check || (cat tests/rngtesturandom.sh.log && + cat tests/rngtestzero.sh.log && cat ./tests/test-suite.log) + - sudo make install diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rng-tools-6.10/configure.ac new/rng-tools-6.11/configure.ac --- old/rng-tools-6.10/configure.ac 2020-03-27 17:52:27.000000000 +0100 +++ new/rng-tools-6.11/configure.ac 2021-01-08 15:06:59.000000000 +0100 @@ -17,7 +17,7 @@ dnl along with this program; if not, write to the Free Software dnl Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA -AC_INIT(rng-tools, 6.10, [Neil Horman <nhor...@tuxdriver.com>]) +AC_INIT(rng-tools, 6.11, [Neil Horman <nhor...@tuxdriver.com>]) AC_PREREQ(2.52) AC_CONFIG_SRCDIR([rngd.c]) AC_CANONICAL_TARGET @@ -43,7 +43,7 @@ AC_ARG_WITH([rtlsdr], AS_HELP_STRING([--without-rtlsdr], - [Disable rtlsdr support. ]) + [Disable rtlsdr support. ]), [], [with_rtlsdr=no] ) @@ -91,7 +91,7 @@ AC_SEARCH_LIBS(jent_version,jitterentropy, [AM_CONDITIONAL([JITTER], [true]) AC_DEFINE([HAVE_JITTER],1,[Enable JITTER])], - AC_MSG_NOTICE([No Jitterentropy library found])) + AC_MSG_NOTICE([No Jitterentropy library found]),-lpthread) ], [AC_MSG_NOTICE([Disabling JITTER entropy source])] ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rng-tools-6.10/fips.c new/rng-tools-6.11/fips.c --- old/rng-tools-6.10/fips.c 2020-03-27 17:52:27.000000000 +0100 +++ new/rng-tools-6.11/fips.c 2021-01-08 15:06:59.000000000 +0100 @@ -93,11 +93,10 @@ 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)]++; + if (ctx->rlength > 4) { + ctx->runs[5 + (6 * ctx->last_bit)]++; + } else if (ctx->rlength >= 0 ) { + ctx->runs[ctx->rlength + (6 * ctx->last_bit)]++; } /* Check if we just failed longrun test */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rng-tools-6.10/rngd.8.in new/rng-tools-6.11/rngd.8.in --- old/rng-tools-6.10/rngd.8.in 2020-03-27 17:52:27.000000000 +0100 +++ new/rng-tools-6.11/rngd.8.in 2021-01-08 15:06:59.000000000 +0100 @@ -21,6 +21,7 @@ [\fB\-s\fR, \fB\-\-random-step=\fInnn\fR] [\fB\-t\fR, \fB\-\-test\fR] [\fB\-W\fR, \fB\-\-fill-watermark=\fInnn\fR] +[\fB\-R\fR, \fB\-\-force_reseed=\fInnn\fR] [\fB\-q\fR, \fB\-\-quiet\fR] [\fB\-?\fR, \fB\-\-help\fR] [\fB\-V\fR, \fB\-\-version\fR] @@ -108,7 +109,12 @@ starves. Do not set \fIfill-watermark\fR above the size of the entropy pool (usually 4096 bits). A value of 0 to this option will cause no watermark to be set. - +.TP +\fB\-R\fI n\fR, \fB\-\-force_reseed=\fInnn\fR +For newer kernels which support non-blocking entropy pools, it is still +beneficial to periodically add fresh entropy as a reseeding event. +--force_reseed defines the number of seconds between which fresh entropy is +added to the kernel entropy pool. Defaults to 5 minutes. .TP \fB\-q\fR, \fB\-\-quiet\fR Suppress all messages diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rng-tools-6.10/rngd.c new/rng-tools-6.11/rngd.c --- old/rng-tools-6.10/rngd.c 2020-03-27 17:52:27.000000000 +0100 +++ new/rng-tools-6.11/rngd.c 2021-01-08 15:06:59.000000000 +0100 @@ -66,7 +66,7 @@ bool msg_squash = false; /* True if we want no messages on the console */ bool quiet = false; /* True if we want no console output at all */ volatile bool server_running = true; /* set to false, to stop daemon */ - +bool do_reseed = false; /* force a reseed event */ bool ignorefail = false; /* true if we ignore MAX_RNG_FAILURES */ /* Command line arguments and processing */ @@ -115,7 +115,7 @@ "Number of bytes written to random-device at a time (default: 64)" }, { "fill-watermark", 'W', "n", 0, - "Do not stop feeding entropy to random-device until at least n bits of entropy are available in the pool (default: 2048), 0 <= n <= 4096" }, + "Do not stop feeding entropy to random-device until at least n bits of entropy are available in the pool (default: 3/4 of poolsize), 0 <= n <= 4096" }, { "quiet", 'q', 0, 0, "Suppress all messages" }, @@ -123,6 +123,8 @@ { "entropy-count", 'e', "n", 0, "Number of entropy bits to support (default: 8), 1 <= n <= 8" }, + { "force-reseed", 'R', "n", 0, "Time in seconds to force adding entropy to the random device" }, + { 0 }, }; @@ -135,6 +137,7 @@ .list = false, .ignorefail = false, .entropy_count = 8, + .force_reseed = 60 * 5, }; struct arguments *arguments = &default_arguments; @@ -235,6 +238,17 @@ } }; +static struct rng_option nist_options[] = { + [NIST_OPT_USE_AES] = { + .key = "use_aes", + .type = VAL_INT, + .int_val = 1, + }, + { + .key = NULL, + } +}; + static struct rng_option rtlsdr_options[] = { [RTLSDR_OPT_DEVID] = { .key = "device_id", @@ -260,6 +274,9 @@ .key = "sample_max", .type = VAL_INT, .int_val = 2800000, + }, + { + .key = NULL, } }; @@ -325,7 +342,7 @@ .init = init_nist_entropy_source, #endif .disabled = true, - .rng_options = NULL, + .rng_options = nist_options, }, { .rng_name = "JITTER Entropy generator", @@ -402,7 +419,7 @@ } else { idx = strtoul(name_idx, NULL, 10); if ((idx == LONG_MAX) || (idx >= ENT_MAX)) { - message(LOG_CONS|LOG_INFO, "option index out of range: %u\n", idx); + message(LOG_CONS|LOG_INFO, "option index out of range: %d\n", idx); return -ERANGE; } message(LOG_CONS|LOG_INFO, "Note, reference of entropy sources by index " @@ -493,7 +510,7 @@ } options++; } - message(LOG_CONS|LOG_INFO, "Option %s not found for source idx %lu\n", optkey, idx); + message(LOG_CONS|LOG_INFO, "Option %s not found for source idx %ld\n", optkey, idx); return -ERANGE; break; @@ -503,7 +520,7 @@ return idx; entropy_sources[idx].disabled = true; - message(LOG_CONS|LOG_INFO, "Disabling %lu: %s (%s)\n", idx, + message(LOG_CONS|LOG_INFO, "Disabling %ld: %s (%s)\n", idx, entropy_sources[idx].rng_name, entropy_sources[idx].rng_sname); break; case 'n': @@ -512,7 +529,7 @@ return idx; entropy_sources[idx].disabled = false; - message(LOG_CONS|LOG_INFO, "Enabling %lu: %s (%s)\n", idx, + message(LOG_CONS|LOG_INFO, "Enabling %ld: %s (%s)\n", idx, entropy_sources[idx].rng_name, entropy_sources[idx].rng_sname); break; case 'l': @@ -563,6 +580,14 @@ arguments->entropy_count = e; break; } + case 'R': { + int R; + if ((sscanf(arg,"%i", &R) == 0) || (R < 0)) + argp_usage(state); + else + arguments->force_reseed = R; + break; + } default: return ARGP_ERR_UNKNOWN; } @@ -588,6 +613,10 @@ p += random_step) { if (!server_running) return 0; + if (do_reseed) { + do_reseed = false; + alarm(arguments->force_reseed); + } rc = random_add_entropy(p, random_step); if (rc == -1) return 1; @@ -731,6 +760,11 @@ server_running = false; } +static void force_reseed_signal(int signo) +{ + do_reseed = true; +} + static void alarm_signal(int signo) { double bits_gathered; @@ -857,7 +891,7 @@ message(LOG_CONS|LOG_INFO, "%d: %s (%s)\n", i, entropy_sources[i].rng_name, entropy_sources[i].rng_sname); } - + quiet = true; close_all_entropy_sources(); return rc; } @@ -882,6 +916,14 @@ message(LOG_CONS|LOG_INFO, "Entering test mode...no entropy will " "be delivered to the kernel\n"); signal(SIGALRM, alarm_signal); + } else { + /* + * Use the alarm signal instead to wake us up on the force_reseed value + */ + if (arguments->force_reseed) { + signal(SIGALRM, force_reseed_signal); + alarm(arguments->force_reseed); + } } if (arguments->ignorefail) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rng-tools-6.10/rngd.h new/rng-tools-6.11/rngd.h --- old/rng-tools-6.10/rngd.h 2020-03-27 17:52:27.000000000 +0100 +++ new/rng-tools-6.11/rngd.h 2021-01-08 15:06:59.000000000 +0100 @@ -58,6 +58,7 @@ bool enable_drng; bool enable_tpm; int entropy_count; + int force_reseed; }; extern struct arguments *arguments; @@ -99,6 +100,14 @@ }; /* + * NIST options + */ +enum { + NIST_OPT_USE_AES = 0, + NIST_OPT_MAX, +}; + +/* * RTLSDR options */ enum { @@ -157,13 +166,13 @@ #define message(priority,fmt,args...) do { \ if (quiet) \ break;\ + if (arguments->debug == false && LOG_PRI(priority) == LOG_DEBUG) \ + break;\ if (am_daemon) { \ syslog((priority), fmt, ##args); \ } else if (!msg_squash) { \ - if ((LOG_PRI(priority) != LOG_DEBUG) || (arguments->debug == true)) {\ - fprintf(stderr, fmt, ##args); \ - fflush(stderr); \ - } \ + fprintf(stderr, fmt, ##args); \ + fflush(stderr); \ } \ } while (0) @@ -178,6 +187,7 @@ free(____buf); \ } while (0) +extern bool do_reseed; extern volatile bool server_running; extern int write_pid_file(const char *pid_fn); #endif /* RNGD__H */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rng-tools-6.10/rngd.service new/rng-tools-6.11/rngd.service --- old/rng-tools-6.10/rngd.service 1970-01-01 01:00:00.000000000 +0100 +++ new/rng-tools-6.11/rngd.service 2021-01-08 15:06:59.000000000 +0100 @@ -0,0 +1,9 @@ +[Unit] +Description=Hardware RNG Entropy Gatherer Daemon +ConditionVirtualization=!container + +[Service] +ExecStart=/usr/sbin/rngd -f + +[Install] +WantedBy=multi-user.target diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rng-tools-6.10/rngd_darn.c new/rng-tools-6.11/rngd_darn.c --- old/rng-tools-6.10/rngd_darn.c 2020-03-27 17:52:27.000000000 +0100 +++ new/rng-tools-6.11/rngd_darn.c 2021-01-08 15:06:59.000000000 +0100 @@ -46,7 +46,7 @@ _x < _y ? _x : _y; }) static uint64_t get_darn(); -static int refill_rand(struct rng *ent_src); +static int refill_rand(struct rng *ent_src, bool allow_reinit); static size_t copy_avail_rand_to_buf(unsigned char *buf, size_t size, size_t copied); #define AES_BLOCK 16 @@ -67,7 +67,7 @@ static size_t darn_buf_avail = 0; static size_t darn_buf_ptr = CHUNK_SIZE - 1; -static size_t rekey_thresh = (1 << THRESH_BITS); +static size_t rekey_thresh = 0; static size_t rand_bytes_served = 0; static int init_openssl(struct rng *ent_src) @@ -100,7 +100,7 @@ return 1; rand_bytes_served = 0; - if (refill_rand(ent_src)) + if (refill_rand(ent_src, false)) return 1; if (copy_avail_rand_to_buf((unsigned char *)&rekey_thresh, sizeof(size_t), 0) < sizeof(size_t)) return 1; @@ -109,7 +109,7 @@ return 0; } -int encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key, +static int osslencrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key, unsigned char *iv, unsigned char *ciphertext) { int len; @@ -138,7 +138,7 @@ return ciphertext_len; } -static inline int openssl_mangle(unsigned char *tmp, struct rng *ent_src) +static inline int openssl_mangle(unsigned char *tmp, size_t size, struct rng *ent_src) { int ciphertext_len; @@ -150,30 +150,29 @@ unsigned char ciphertext[CHUNK_SIZE * RDRAND_ROUNDS]; /* Encrypt the plaintext */ - ciphertext_len = encrypt (tmp, strlen(tmp), key, iv_buf, + ciphertext_len = osslencrypt (tmp, size, key, iv_buf, ciphertext); - printf("Calling mangle with len %d\n", ciphertext_len); if (!ciphertext_len) return -1; - memcpy(tmp, ciphertext, strlen(tmp)); + memcpy(tmp, ciphertext, size); return 0; } -static int refill_rand(struct rng *ent_src) +static int refill_rand(struct rng *ent_src, bool allow_reinit) { int i; if (darn_buf_avail) return 0; if (ent_src->rng_options[DARN_OPT_AES].int_val) { - if (rand_bytes_served >= rekey_thresh) { + if (allow_reinit && (rand_bytes_served >= rekey_thresh)) { message_entsrc(ent_src,LOG_DAEMON|LOG_DEBUG, "rekeying DARN rng\n"); if (init_openssl(ent_src)) return 1; } - if (openssl_mangle(darn_rand_buf, ent_src)) { + if (openssl_mangle(darn_rand_buf, CHUNK_SIZE, ent_src)) { return 1; } } else { @@ -228,11 +227,10 @@ int xread_darn(void *buf, size_t size, struct rng *ent_src) { uint64_t *darn_ptr =(uint64_t *)buf; - uint64_t darn_val; size_t copied = 0; while (copied < size) { - if (refill_rand(ent_src)) { + if (refill_rand(ent_src, true)) { return 1; } copied += copy_avail_rand_to_buf(buf, size, copied); @@ -247,11 +245,13 @@ { if (!(getauxval(AT_HWCAP2) & PPC_FEATURE2_DARN)) { + message_entsrc(ent_src, LOG_DAEMON|LOG_INFO, "No HW SUPPORT\n"); return 1; } - if (init_openssl(ent_src)) + if (refill_rand(ent_src, true)) return 1; + message_entsrc(ent_src,LOG_DAEMON|LOG_INFO, "Enabling power DARN rng support\n"); return 0; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rng-tools-6.10/rngd_jitter.c new/rng-tools-6.11/rngd_jitter.c --- old/rng-tools-6.10/rngd_jitter.c 2020-03-27 17:52:27.000000000 +0100 +++ new/rng-tools-6.11/rngd_jitter.c 2021-01-08 15:06:59.000000000 +0100 @@ -69,10 +69,10 @@ unsigned char *aes_buf; -char key[AES_BLOCK]; +static char key[AES_BLOCK]; static unsigned char iv_buf[CHUNK_SIZE] __attribute__((aligned(128))); -static int encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key, +static int osslencrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key, unsigned char *iv, unsigned char *ciphertext) { EVP_CIPHER_CTX *ctx; @@ -122,7 +122,7 @@ unsigned char ciphertext[CHUNK_SIZE * RDRAND_ROUNDS]; /* Encrypt the plaintext */ - ciphertext_len = encrypt (tmp, strlen(tmp), key, iv_buf, + ciphertext_len = osslencrypt (tmp, strlen(tmp), key, iv_buf, ciphertext); if (!ciphertext_len) return -1; @@ -143,7 +143,7 @@ size_t total; try_again: while (need) { - message_entsrc(ent_src,LOG_DAEMON|LOG_DEBUG, "xread_jitter requests %lu bytes from pipe\n", need); + message_entsrc(ent_src,LOG_DAEMON|LOG_DEBUG, "xread_jitter requests %d bytes from pipe\n", need); request = read(pipefds[0], &bptr[size-need], need); if ((request < need) && ent_src->rng_options[JITTER_OPT_USE_AES].int_val) { message_entsrc(ent_src,LOG_DAEMON|LOG_DEBUG, "xread_jitter falls back to AES\n"); @@ -447,10 +447,6 @@ pthread_mutex_unlock(&tdata[i].statemtx); } - flags = fcntl(pipefds[0], F_GETFL, 0); - flags |= O_NONBLOCK; - fcntl(pipefds[0], F_SETFL, &flags); - if (ent_src->rng_options[JITTER_OPT_USE_AES].int_val) { /* * Temporarily disable aes so we don't try to use it during init @@ -468,7 +464,23 @@ ent_src->rng_options[JITTER_OPT_USE_AES].int_val = 1; } xread_jitter(aes_buf, tdata[0].buf_sz, ent_src); + } else { + /* + * Make sure that an entropy gathering thread has generated + * at least some entropy before setting O_NONBLOCK and finishing + * the entropy source initialization. + * + * This avoids "Entropy Generation is slow" log spamming that + * would otherwise happen until jent_read_entropy() has run + * for the first time. + */ + xread_jitter(&i, 1, ent_src); } + + flags = fcntl(pipefds[0], F_GETFL, 0); + flags |= O_NONBLOCK; + fcntl(pipefds[0], F_SETFL, flags); + message_entsrc(ent_src,LOG_DAEMON|LOG_INFO, "Enabling JITTER rng support\n"); return 0; } @@ -476,8 +488,6 @@ void close_jitter_entropy_source(struct rng *ent_src) { int i; - char tmpbuf[1024]; - int flags; /* Close the pipes to prevent further writing */ close(pipefds[1]); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rng-tools-6.10/rngd_linux.c new/rng-tools-6.11/rngd_linux.c --- old/rng-tools-6.10/rngd_linux.c 2020-03-27 17:52:27.000000000 +0100 +++ new/rng-tools-6.11/rngd_linux.c 2021-01-08 15:06:59.000000000 +0100 @@ -67,7 +67,7 @@ /* * Default to 4096 if fscanf fails */ - if(fscanf(f,"%d", &wm) < 1) + if(fscanf(f,"%u", &wm) < 1) wm = 4096; kent_pool_size = wm; wm = wm*3/4; @@ -102,7 +102,7 @@ if (!f) { err = 1; } else { - fprintf(f, "%u\n", arguments->fill_watermark); + fprintf(f, "%d\n", arguments->fill_watermark); /* Note | not || here... we always want to close the file */ err = ferror(f) | fclose(f); } @@ -130,7 +130,7 @@ memcpy(ent + 1, buf, size); if (write_to_output == false) { - if (ioctl(random_fd, RNDADDENTROPY, ent) != 0) { + if (ioctl(random_fd, RNDADDENTROPY, ent) < 0) { if (errno == ENOTTY && !arguments->daemon) { /* * This isn't a real random device. @@ -160,8 +160,8 @@ void random_sleep(void) { struct pollfd pfd = { - fd: random_fd, - events: POLLOUT, + .fd = random_fd, + .events = POLLOUT, }; poll(&pfd, 1, -1); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rng-tools-6.10/rngd_nistbeacon.c new/rng-tools-6.11/rngd_nistbeacon.c --- old/rng-tools-6.10/rngd_nistbeacon.c 2020-03-27 17:52:27.000000000 +0100 +++ new/rng-tools-6.11/rngd_nistbeacon.c 2021-01-08 15:06:59.000000000 +0100 @@ -63,6 +63,12 @@ #define NIST_BUF_SIZE 64 #define NIST_CERT "/home/nhorman/Downloads/beacon.cer" +#ifdef CLOCK_MONOTONIC_COARSE +#define NIST_CLOCK_SOURCE CLOCK_MONOTONIC_COARSE +#else +#define NIST_CLOCK_SOURCE CLOCK_MONOTONIC +#endif + static int get_nist_record(struct rng *ent_src); @@ -126,22 +132,107 @@ BIO *bfp = NULL; X509 *cert = NULL; EVP_PKEY *pubkey; -uint32_t lastpulse = 0; +uint64_t lastpulse = 0; + +#define AES_BLOCK 16 +#define CHUNK_SIZE (AES_BLOCK*8) /* 8 parallel streams */ +#define RDRAND_ROUNDS 512 /* 512:1 data reduction */ +static unsigned char key[AES_BLOCK] = {0,}; + +static int osslencrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key, + unsigned char *iv, unsigned char *ciphertext) +{ + EVP_CIPHER_CTX *ctx; + + int len; + + int ciphertext_len; + + /* Create and initialise the context */ + if(!(ctx = EVP_CIPHER_CTX_new())) + return 0; + + if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv)) + return 0; + /* + * Provide the message to be encrypted, and obtain the encrypted output. + * EVP_EncryptUpdate can be called multiple times if necessary + */ + if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len)) + return 0; + + ciphertext_len = len; + + /* + * Finalise the encryption. Further ciphertext bytes may be written at + * this stage. + */ + if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) + return 0; + ciphertext_len += len; + + /* Clean up */ + EVP_CIPHER_CTX_free(ctx); + + return ciphertext_len; +} + +static inline int openssl_mangle(unsigned char *tmp, size_t size, struct rng *ent_src) +{ + unsigned char xkey[AES_BLOCK]; /* Material to XOR into the key */ + unsigned char iv_buf[CHUNK_SIZE]; + int i; + int ciphertext_len; + + /* + * Buffer for ciphertext. Ensure the buffer is long enough for the + * ciphertext which may be longer than the plaintext, depending on the + * algorithm and mode. + */ + unsigned char ciphertext[CHUNK_SIZE * RDRAND_ROUNDS]; + + for(i=0; i < AES_BLOCK; i++) + key[i] = key[i] ^ xkey[i]; + + /* Encrypt the plaintext */ + ciphertext_len = osslencrypt (tmp, size, key, iv_buf, + ciphertext); + if (!ciphertext_len) + return -1; + + memcpy(tmp, ciphertext, size); + return 0; +} static int refill_rand(struct rng *ent_src) { + static struct timespec last = {0, 0}; + struct timespec now; if (nist_buf_avail > 0) return 0; - if (get_nist_record(ent_src)) - return 1; - if (block.pulseIndex == lastpulse) - return 0; + clock_gettime(NIST_CLOCK_SOURCE, &now); + if (last.tv_sec == 0 || (now.tv_sec-last.tv_sec > 60)) { + last.tv_sec = now.tv_sec; + message_entsrc(ent_src, LOG_DAEMON|LOG_DEBUG, "Getting new record\n"); + if (get_nist_record(ent_src)) + return 1; + } + if (block.pulseIndex == lastpulse) { + if (ent_src->rng_options[NIST_OPT_USE_AES].int_val) { + if (openssl_mangle(nist_rand_buf, NIST_BUF_SIZE, ent_src) != 0) { + message_entsrc(ent_src, LOG_DAEMON|LOG_DEBUG, "Failed mangle\n"); + return 1; + } + goto fresh_buffer; + } else + return 0; + } memcpy(nist_rand_buf, block.outputValue, be32toh(block.outputValueLen)); - nist_buf_avail = be32toh(block.outputValueLen); - +fresh_buffer: + nist_buf_avail = NIST_BUF_SIZE; nist_buf_ptr = 0; return 0; @@ -170,11 +261,12 @@ */ if (server_running == false) return 1; - if (refill_rand(ent_src)) + if ((nist_buf_avail == 0) && refill_rand(ent_src)) return 1; if (nist_buf_avail == 0) return 1; copied += copy_avail_rand_to_buf(buf, size, copied); + message_entsrc(ent_src, LOG_DAEMON|LOG_DEBUG, "Got %zu/%zu bytes data\n", copied, size); } return 0; } @@ -186,7 +278,7 @@ uint32_t slen; json_t *obj = json_object_get(parent, key); tmpval = json_string_value(obj); - slen = json_string_length(obj); + slen = strlen(tmpval); *val = strdup(tmpval); if (len != NULL) *len = htobe32(slen); @@ -212,11 +304,12 @@ bool unibble; int i,j; json_t *obj = json_object_get(parent, key); - uint32_t rawlen = json_string_length(obj); + uint32_t rawlen; const char *rawstring = json_string_value(obj); char *newval; char tmpval; + rawlen = strlen(rawstring); if (rawlen%2) message(LOG_DAEMON|LOG_ERR, "Byte array isn't of even length!\n"); @@ -558,7 +651,7 @@ curl_easy_setopt(curl, CURLOPT_URL, certurl); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, copy_nist_certificate); - curl_easy_perform(curl); + res = curl_easy_perform(curl); if (res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed in cert update: %s\n", curl_easy_strerror(res)); @@ -572,12 +665,6 @@ CURL *curl; CURLcode res; int rc = 1; - struct timeval ct; - - /* - * record our previous pulse index - */ - lastpulse = block.pulseIndex; curl = curl_easy_init(); @@ -597,6 +684,8 @@ curl_easy_cleanup(curl); + lastpulse = block.pulseIndex; + if (!activeCertId || memcmp(activeCertId, block.certificateId, be32toh(block.certificateIdLen))) { free(activeCertId); activeCertId = strndup(block.certificateId, be32toh(block.certificateIdLen)); @@ -631,5 +720,6 @@ "Do not use this source in any entropy pool " "which generates cryptographic objects!\n"); } + return rc; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rng-tools-6.10/rngd_rtlsdr.c new/rng-tools-6.11/rngd_rtlsdr.c --- old/rng-tools-6.10/rngd_rtlsdr.c 2020-03-27 17:52:27.000000000 +0100 +++ new/rng-tools-6.11/rngd_rtlsdr.c 2021-01-08 15:06:59.000000000 +0100 @@ -180,7 +180,7 @@ * Finalise the encryption. Further ciphertext bytes may be written at * this stage. */ - if(1 != EVP_EncryptFinal_ex(ctx, out + len, &len)) + if(1 != EVP_EncryptFinal_ex(ctx, out, &len)) return 0; ciphertext_len += len; @@ -196,9 +196,8 @@ int rc; int read_len; size_t gen_len; - int i; char *buf_ptr = buf; - unsigned char outbuf[RAW_BUF_SZ]; + unsigned char outbuf[RAW_BUF_SZ + EVP_MAX_BLOCK_LENGTH]; size_t copy_size; size_t total_size = 0; while (total_size < size) {