diff --git a/.gitignore b/.gitignore index 4cf660d..24cf979 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -/rng-tools-6.12.tar.gz +/rng-tools-6.13.tar.gz diff --git a/0001-Use-AM_PROG_AR-over-AC_CHECK_TOOLS.patch b/0001-Use-AM_PROG_AR-over-AC_CHECK_TOOLS.patch new file mode 100644 index 0000000..66afbdb --- /dev/null +++ b/0001-Use-AM_PROG_AR-over-AC_CHECK_TOOLS.patch @@ -0,0 +1,45 @@ +From 16b728f9a5bb138386fa770de817ec244a158be5 Mon Sep 17 00:00:00 2001 +From: David Seifert +Date: Sat, 12 Jun 2021 22:15:06 +0200 +Subject: Use `AM_PROG_AR` over `AC_CHECK_TOOLS` + +* `AM_PROG_AR` is the canonical way to detect the archiver + and includes workarounds for Cygwin. + +Signed-off-by: Vladis Dronov +--- + .gitignore | 1 + + configure.ac | 3 +-- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/.gitignore b/.gitignore +index 0df9347..5dc334d 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -2,6 +2,7 @@ + *.o + /.deps/ + /aclocal.m4 ++/ar-lib + /autom4te.cache/ + /compile + /config.guess +diff --git a/configure.ac b/configure.ac +index 5b4f2cb..1cb7fd7 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -62,10 +62,9 @@ AM_PROG_AS + dnl Checks for programs + AC_PROG_CC + AC_PROG_RANLIB ++AM_PROG_AR + AC_PROG_GCC_TRADITIONAL + +-AC_CHECK_TOOLS([AR], [ar gar], :) +- + AX_PTHREAD + + AM_CONDITIONAL([RDRAND], [test $target_cpu = x86_64 -o $target_cpu = i686]) +-- +2.26.3 + diff --git a/0003-AC_CANONICAL_TARGET-AC_CANONICAL_HOST.patch b/0003-AC_CANONICAL_TARGET-AC_CANONICAL_HOST.patch new file mode 100644 index 0000000..be19d6e --- /dev/null +++ b/0003-AC_CANONICAL_TARGET-AC_CANONICAL_HOST.patch @@ -0,0 +1,52 @@ +From 3adf2613e262efbda0a3455e59c8cb3390271563 Mon Sep 17 00:00:00 2001 +From: David Seifert +Date: Sat, 12 Jun 2021 22:15:12 +0200 +Subject: `AC_CANONICAL_TARGET` -> `AC_CANONICAL_HOST` + +* `AC_CANONICAL_TARGET` is the type of system for which code + will be produced, not on which it will run. This is a common + confusion with Autoconf's target triplet. + +Signed-off-by: Vladis Dronov +--- + configure.ac | 15 ++++++++------- + 1 file changed, 8 insertions(+), 7 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 1cb7fd7..0fe06fc 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -20,7 +20,8 @@ dnl Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA + AC_INIT(rng-tools, 6.13, [Neil Horman ]) + AC_PREREQ(2.52) + AC_CONFIG_SRCDIR([rngd.c]) +-AC_CANONICAL_TARGET ++AC_CANONICAL_HOST ++AC_CANONICAL_TARGET dnl required for broken AX_PTHREAD + AM_INIT_AUTOMAKE([foreign]) + AC_CONFIG_HEADERS([rng-tools-config.h]) + AC_CONFIG_MACRO_DIRS([m4]) +@@ -67,14 +68,14 @@ AC_PROG_GCC_TRADITIONAL + + AX_PTHREAD + +-AM_CONDITIONAL([RDRAND], [test $target_cpu = x86_64 -o $target_cpu = i686]) +-AS_IF([test $target_cpu = x86_64 -o $target_cpu = i686], [AC_DEFINE([HAVE_RDRAND],1,[Enable RDRAND])],[]) ++AM_CONDITIONAL([RDRAND], [test $host_cpu = x86_64 || $host_cpu = i686]) ++AS_IF([test $host_cpu = x86_64 || $host_cpu = i686], [AC_DEFINE([HAVE_RDRAND],1,[Enable RDRAND])],[]) + +-AM_CONDITIONAL([DARN], [test $target_cpu = powerpc64le]) +-AS_IF([test $target_cpu = powerpc64le], [AC_DEFINE([HAVE_DARN],1,[Enable DARN])],[]) ++AM_CONDITIONAL([DARN], [test $host_cpu = powerpc64le]) ++AS_IF([test $host_cpu = powerpc64le], [AC_DEFINE([HAVE_DARN],1,[Enable DARN])],[]) + +-AM_CONDITIONAL([RNDR], [test $target_cpu = aarch64]) +-AS_IF([test $target_cpu = aarch64], [AC_DEFINE([HAVE_RNDR],1,[Enable RNDR])],[]) ++AM_CONDITIONAL([RNDR], [test $host_cpu = aarch64]) ++AS_IF([test $host_cpu = aarch64], [AC_DEFINE([HAVE_RNDR],1,[Enable RNDR])],[]) + AM_CONDITIONAL([JITTER], [false]) + + AC_ARG_ENABLE(jitterentropy, +-- +2.26.3 + diff --git a/0004-Fix-logic-in-ossl_aes_random_key.patch b/0004-Fix-logic-in-ossl_aes_random_key.patch new file mode 100644 index 0000000..b2f39dc --- /dev/null +++ b/0004-Fix-logic-in-ossl_aes_random_key.patch @@ -0,0 +1,69 @@ +From 73e81dc78ddb6f1bc0d8750c1a9e19e6cc123d48 Mon Sep 17 00:00:00 2001 +From: Vladis Dronov +Date: Sat, 12 Jun 2021 09:16:25 +0200 +Subject: Fix logic in ossl_aes_random_key() + +- Using sizeof is correct for arr[], but is not correct for *ptr. read() here +makes a 8-bytes read (on 64-bit arch). It should read AES_BLOCK bytes instead, +as callers of ossl_aes_random_key() imply. + +Covscan emits the following warning: + +Error: SIZEOF_MISMATCH (CWE-398): [#def1] +rng-tools-6.12/ossl_helpers.c:51: suspicious_sizeof: Passing argument "key" of +type "unsigned char *" and argument "8UL /* sizeof (key) */" to function "read" +is suspicious. + 51|-> int r = read(fd, key, sizeof key); + +- According to the following warning, mark r as not used explicitly: + +Error: CLANG_WARNING: [#def2] +rng-tools-6.12/ossl_helpers.c:51:7: warning[deadcode.DeadStores]: Value stored +to 'r' during its initialization is never read + 51|-> int r = read(fd, key, sizeof key); + +- Add volatile to stack_junk to avoid possible compiler optimization. This does +not silence "Uninitialized variable: stack_junk" covscan warning. + +- Remove a check for pepper == NULL where it is not needed. + +Signed-off-by: Vladis Dronov +--- + ossl_helpers.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/ossl_helpers.c b/ossl_helpers.c +index c3c1fbb..9569b74 100644 +--- a/ossl_helpers.c ++++ b/ossl_helpers.c +@@ -42,22 +42,23 @@ void ossl_aes_random_key(unsigned char *key, const unsigned char *pepper) + 0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70, + 0x80,0x90,0xa0,0xb0,0xc0,0xd0,0xe0,0xf0 + }; /* AES data reduction key */ +- unsigned char stack_junk[AES_BLOCK]; ++ volatile unsigned char stack_junk[AES_BLOCK]; + int fd, i; + + /* Try getting some randomness from the kernel */ + fd = open("/dev/urandom", O_RDONLY); + if (fd >= 0) { +- int r = read(fd, key, sizeof key); ++ int r __attribute__((unused)); ++ r = read(fd, key, AES_BLOCK); + close(fd); + } + + /* Mix in our default key */ +- for (i = 0; i < AES_BLOCK && pepper; i++) ++ for (i = 0; i < AES_BLOCK; i++) + key[i] ^= default_key[i]; + + /* Mix in stack junk */ +- for (i = 0; i < AES_BLOCK && pepper; i++) ++ for (i = 0; i < AES_BLOCK; i++) + key[i] ^= stack_junk[i]; + + /* Spice it up if we can */ +-- +2.26.3 + diff --git a/0005-Fix-a-read-returning-zero-case-in-init_entropy_sourc.patch b/0005-Fix-a-read-returning-zero-case-in-init_entropy_sourc.patch new file mode 100644 index 0000000..2263443 --- /dev/null +++ b/0005-Fix-a-read-returning-zero-case-in-init_entropy_sourc.patch @@ -0,0 +1,44 @@ +From 8659477ea65b1617332efee6da4c533137870577 Mon Sep 17 00:00:00 2001 +From: Vladis Dronov +Date: Sat, 12 Jun 2021 09:00:42 +0200 +Subject: Fix a read() returning zero case in init_entropy_source() + +Covscan warns about this with: + +Error: CHECKED_RETURN (CWE-252): [#def3] +rng-tools-6.12/rngd_entsource.c:185: check_return: "read(int, void *, +size_t)" returns the number of bytes read, but it is ignored. + 185|-> if (read(rngavail_fd, buf, sizeof(buf)) < 0) { + +Add a check for a zero return. While this should not happen, lets just +handle the case, also to silence covscan. + +Signed-off-by: Vladis Dronov +--- + rngd_entsource.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/rngd_entsource.c b/rngd_entsource.c +index f54ee40..e5b7d43 100644 +--- a/rngd_entsource.c ++++ b/rngd_entsource.c +@@ -182,13 +182,14 @@ int init_entropy_source(struct rng *ent_src) + return 1; + } + +- if (read(rngavail_fd, buf, sizeof(buf)) < 0) { ++ int ret = read(rngavail_fd, buf, sizeof(buf)); ++ if (ret < 0) { + message_entsrc(ent_src,LOG_DAEMON|LOG_DEBUG, "Error reading sysfs file: %s\n", RNG_AVAIL); + close(rngavail_fd); + return 1; + } + +- if (strncmp(buf, "\n", 1) == 0) { ++ if (ret == 0 || strncmp(buf, "\n", 1) == 0) { + message_entsrc(ent_src,LOG_DAEMON|LOG_DEBUG, "No available rng device\n"); + close(rngavail_fd); + return 1; +-- +2.26.3 + diff --git a/0006-Fix-minor-possibilities-of-using-a-NULL-pointer.patch b/0006-Fix-minor-possibilities-of-using-a-NULL-pointer.patch new file mode 100644 index 0000000..d6d0ae6 --- /dev/null +++ b/0006-Fix-minor-possibilities-of-using-a-NULL-pointer.patch @@ -0,0 +1,78 @@ +From e4a94ad5d4ea8e5663f1e5d71669317b16105945 Mon Sep 17 00:00:00 2001 +From: Vladis Dronov +Date: Sat, 12 Jun 2021 13:11:19 +0200 +Subject: Fix minor possibilities of using a NULL pointer + +Fix the following covscan warnings by performing a check for a NULL: + +1) Add a check for NULL to message_entsrc macro: + +Error: GCC_ANALYZER_WARNING (CWE-688): +rng-tools-6.12/rngd_rdrand.c: scope_hint: In function 'init_drng_entropy_source' +rng-tools-6.12/rngd.h:186:9: warning[-Wanalyzer-possible-null-argument]: use of +possibly-NULL '____buf' where non-null expected +/usr/include/stdio.h:334:12: note: argument 1 of 'sprintf' must be non-null + 184| size_t ____neededmsg = snprintf(NULL, 0, fmt, ##args) + 1; \ + 185| char *____buf = malloc(____neededpfx + ____neededmsg); \ + 186|-> sprintf(____buf, "[%-6s]: " fmt, src->rng_sname, ##args); \ + +2) Move memset() in xread_tpm() to a proper place: + +Error: NULL_RETURNS (CWE-476): [#def3] +rng-tools-6.12/rngd_entsource.c:96: returned_null: "malloc" returns "NULL" +(checked 89 out of 95 times). +rng-tools-6.12/rngd_entsource.c:96: var_assigned: Assigning: "temp_buf" = +"NULL" return value from "malloc". +rng-tools-6.12/rngd_entsource.c:97: dereference: Dereferencing a pointer +that might be "NULL" "temp_buf" when calling "memset". + 96| temp_buf = (unsigned char *) malloc(size + TPM_GET_RNG_OVERHEAD); + 97|-> memset(temp_buf, 0, (size+TPM_GET_RNG_OVERHEAD)); + 98| if (temp_buf == NULL) { + +Signed-off-by: Vladis Dronov +--- + rngd.h | 8 +++++--- + rngd_entsource.c | 3 ++- + 2 files changed, 7 insertions(+), 4 deletions(-) + +diff --git a/rngd.h b/rngd.h +index 6208b95..7d65f3c 100644 +--- a/rngd.h ++++ b/rngd.h +@@ -184,9 +184,11 @@ extern bool quiet; + size_t ____neededpfx = snprintf(NULL, 0, "[%-6s]: ", src->rng_sname); \ + size_t ____neededmsg = snprintf(NULL, 0, fmt, ##args) + 1; \ + char *____buf = malloc(____neededpfx + ____neededmsg); \ +- sprintf(____buf, "[%-6s]: " fmt, src->rng_sname, ##args); \ +- message(priority, "%s", ____buf); \ +- free(____buf); \ ++ if (____buf) { \ ++ sprintf(____buf, "[%-6s]: " fmt, src->rng_sname, ##args); \ ++ message(priority, "%s", ____buf); \ ++ free(____buf); \ ++ } \ + } while (0) + + extern bool do_reseed; +diff --git a/rngd_entsource.c b/rngd_entsource.c +index e5b7d43..b7ebd15 100644 +--- a/rngd_entsource.c ++++ b/rngd_entsource.c +@@ -94,12 +94,13 @@ int xread_tpm(void *buf, size_t size, struct rng *ent_src) + } + + temp_buf = (unsigned char *) malloc(size + TPM_GET_RNG_OVERHEAD); +- memset(temp_buf, 0, (size+TPM_GET_RNG_OVERHEAD)); + if (temp_buf == NULL) { + message_entsrc(ent_src,LOG_ERR|LOG_INFO,"No memory for TPM buffer\n"); + close(ent_src->rng_fd); + return -1; + } ++ memset(temp_buf, 0, (size+TPM_GET_RNG_OVERHEAD)); ++ + /* 32 bits has been reserved for random byte size */ + rng_cmd[13] = (unsigned char)(size & 0xFF); + rng_cmd[12] = (unsigned char)((size >> 8) & 0xFF); +-- +2.26.3 + diff --git a/0007-Small-bug-and-warning-fixes-per-covscan-report.patch b/0007-Small-bug-and-warning-fixes-per-covscan-report.patch new file mode 100644 index 0000000..00317bd --- /dev/null +++ b/0007-Small-bug-and-warning-fixes-per-covscan-report.patch @@ -0,0 +1,185 @@ +From 2d244c6b5aea8f1a8e70307540d9d95b8111a242 Mon Sep 17 00:00:00 2001 +From: Vladis Dronov +Date: Mon, 14 Jun 2021 14:04:27 +0200 +Subject: Small bug and warning fixes per covscan report + +- Fix a strncpy() bug. + +- Remove unused variables. + +- A small formatting fix. + +- Fix signedness warnings. + +- Add parenthesis to definitions of CHUNK_SIZE. + +- Adjust default_watermark() so wm is set to a default value in all cases. + Also add logging the same way it was done in init_kernel_rng(). + +Signed-off-by: Vladis Dronov +--- + rngd_darn.c | 4 ++-- + rngd_jitter.c | 3 +-- + rngd_linux.c | 31 ++++++++++++++++++++++--------- + rngd_rdrand.c | 2 -- + rngd_rndr.c | 2 +- + rngd_rtlsdr.c | 6 +++--- + stats.c | 2 +- + 7 files changed, 30 insertions(+), 20 deletions(-) + +diff --git a/rngd_darn.c b/rngd_darn.c +index bc8edec..5254195 100644 +--- a/rngd_darn.c ++++ b/rngd_darn.c +@@ -46,9 +46,9 @@ static uint64_t get_darn(); + 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 CHUNK_SIZE AES_BLOCK * 8 ++#define CHUNK_SIZE (AES_BLOCK*8) + #define RDRAND_ROUNDS 512 /* 512:1 data reduction */ +-#define THRESH_BITS 14 ++#define THRESH_BITS 14 + + /* ossl AES context */ + static struct ossl_aes_ctx *ossl_ctx; +diff --git a/rngd_jitter.c b/rngd_jitter.c +index b68c791..7403c02 100644 +--- a/rngd_jitter.c ++++ b/rngd_jitter.c +@@ -128,7 +128,7 @@ int pipefds[2]; + + unsigned char *aes_buf; + +-static char key[AES_BLOCK]; ++static unsigned char key[AES_BLOCK]; + static unsigned char iv_buf[CHUNK_SIZE] __attribute__((aligned(128))); + static struct ossl_aes_ctx *ossl_ctx; + +@@ -322,7 +322,6 @@ int validate_jitter_options(struct rng *ent_src) + int delay = ent_src->rng_options[JITTER_OPT_RETRY_DELAY].int_val; + int rcount = ent_src->rng_options[JITTER_OPT_RETRY_COUNT].int_val; + int soft_timer = ent_src->rng_options[JITTER_OPT_FORCE_INT_TIMER].int_val; +- int num_threads = ent_src->rng_options[JITTER_OPT_THREADS].int_val; + + /* Need at least one thread to do this work */ + if (!threads) { +diff --git a/rngd_linux.c b/rngd_linux.c +index cf4fcdf..c52c62d 100644 +--- a/rngd_linux.c ++++ b/rngd_linux.c +@@ -56,22 +56,35 @@ extern int kent_pool_size; + /* + * Get the default watermark + */ ++ ++#define DEFAULT_WATERMARK_GUESS 4096 ++ + int default_watermark(void) + { + FILE *f; +- unsigned int wm; /* Default guess */ ++ unsigned int wm; + + f = fopen("/proc/sys/kernel/random/poolsize", "r"); +- if (!f) ++ if (!f) { ++ wm = DEFAULT_WATERMARK_GUESS; ++ message(LOG_DAEMON|LOG_ERR, "can't open /proc/sys/kernel/random/poolsize: %s", ++ strerror(errno)); + goto err; +- /* +- * Default to 4096 if fscanf fails +- */ +- if(fscanf(f,"%u", &wm) < 1) +- wm = 4096; ++ } ++ ++ /* Use DEFAULT_WATERMARK_GUESS if fscanf fails */ ++ if(fscanf(f,"%u", &wm) < 1) { ++ wm = DEFAULT_WATERMARK_GUESS; ++ message(LOG_DAEMON|LOG_ERR, "can't read /proc/sys/kernel/random/poolsize: %s", ++ strerror(errno)); ++ } ++ ++err: + kent_pool_size = wm; + wm = wm*3/4; +-err: ++ message(LOG_DAEMON|LOG_ERR, "kernel entropy pool size: %d pool watermark: %d", ++ kent_pool_size, wm); ++ + if (f) + fclose(f); + return wm; +@@ -153,7 +166,7 @@ int random_add_entropy(void *buf, size_t size) + } else + write(random_fd, buf, size); + +- return ent->ent_count; ++ return ent->ent_count; + + } + +diff --git a/rngd_rdrand.c b/rngd_rdrand.c +index cba27a9..caa9d05 100644 +--- a/rngd_rdrand.c ++++ b/rngd_rdrand.c +@@ -243,8 +243,6 @@ int init_drng_entropy_source(struct rng *ent_src) + const uint32_t features_ebx7_rdseed = 1 << 18; + uint32_t max_cpuid_leaf; + unsigned char xkey[AES_BLOCK]; /* Material to XOR into the key */ +- int fd; +- int i; + + if (!x86_has_cpuid()) + return 1; /* No CPUID instruction */ +diff --git a/rngd_rndr.c b/rngd_rndr.c +index 176ce90..79bf2ce 100644 +--- a/rngd_rndr.c ++++ b/rngd_rndr.c +@@ -47,7 +47,7 @@ static struct ossl_aes_ctx *ossl_ctx; + static unsigned char key[AES_BLOCK]; + static unsigned char iv_buf[AES_BLOCK]; + +-#define CHUNK_SIZE AES_BLOCK * 8 ++#define CHUNK_SIZE (AES_BLOCK*8) + static unsigned char aes_buf[CHUNK_SIZE]; + static size_t aes_buf_pos; + #define REKEY_BITS 8 +diff --git a/rngd_rtlsdr.c b/rngd_rtlsdr.c +index 949c8b0..5371905 100644 +--- a/rngd_rtlsdr.c ++++ b/rngd_rtlsdr.c +@@ -21,12 +21,12 @@ + #include "rngd.h" + #include "ossl_helpers.h" + +-#define RAW_BUF_SZ 4096 ++#define RAW_BUF_SZ 4096 + +-#define CHUNK_SIZE (AES_BLOCK*8) /* 8 parallel streams */ ++#define CHUNK_SIZE (AES_BLOCK*8) /* 8 parallel streams */ + + static rtlsdr_dev_t *radio = NULL; +-static char raw_buffera[RAW_BUF_SZ]; ++static unsigned char raw_buffera[RAW_BUF_SZ]; + static int freq_min; + static int freq_max; + static int sample_min; +diff --git a/stats.c b/stats.c +index 5c4036a..a172a35 100644 +--- a/stats.c ++++ b/stats.c +@@ -65,7 +65,7 @@ static void scale_mult_unit(char *unit, int unitsize, + if (mult) + snprintf(unit, unitsize, "%ci%s", multchar[mult-1], baseunit); + else +- strncpy(unit, baseunit, unitsize); ++ strncpy(unit, baseunit, unitsize-1); + } + + /* Computes elapsed time in microseconds */ +-- +2.26.3 + diff --git a/0008-Fix-a-minor-memory-leak-in-rngd_jitter.c.patch b/0008-Fix-a-minor-memory-leak-in-rngd_jitter.c.patch new file mode 100644 index 0000000..d88b1b1 --- /dev/null +++ b/0008-Fix-a-minor-memory-leak-in-rngd_jitter.c.patch @@ -0,0 +1,54 @@ +From 05505f04b9146e3f1225c182d3fdfc2fb51a633f Mon Sep 17 00:00:00 2001 +From: Vladis Dronov +Date: Sat, 12 Jun 2021 09:35:21 +0200 +Subject: Fix a minor memory leak in rngd_jitter.c + +While a leak is short-lived until a process memory is freed, fix it anyway. + +Error: GCC_ANALYZER_WARNING (CWE-401): +rng-tools-6.12/rngd_jitter.c:396:66: warning[-Wanalyzer-malloc-leak]: +leak of 'aes_buf' +rng-tools-6.12/rngd_jitter.c:35: included_from: Included from here. +rng-tools-6.12/rngd_jitter.c:394:17: note: in expansion of macro 'message_entsrc' + +Error: GCC_ANALYZER_WARNING (CWE-401): [#def4] +rng-tools-6.12/rngd_jitter.c: scope_hint: In function 'init_jitter_entropy_source' +rng-tools-6.12/rngd_jitter.c:396:66: warning[-Wanalyzer-malloc-leak]: leak of 'aes_buf' +rng-tools-6.12/rngd_jitter.c:394:17: note: in expansion of macro 'message_entsrc' + 394| message_entsrc(ent_src,LOG_CONS|LOG_INFO, "Initializing AES buffer\n"); + 395| aes_buf = malloc(tdata[0].buf_sz); + 396|-> ent_src->rng_options[JITTER_OPT_USE_AES].int_val = 0; + 397| if (xread_jitter(key, AES_BLOCK, ent_src)) { + +Signed-off-by: Vladis Dronov +--- + rngd_jitter.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/rngd_jitter.c b/rngd_jitter.c +index 7403c02..ea29436 100644 +--- a/rngd_jitter.c ++++ b/rngd_jitter.c +@@ -126,7 +126,7 @@ static struct thread_data *tdata; + static pthread_t *threads; + int pipefds[2]; + +-unsigned char *aes_buf; ++unsigned char *aes_buf = NULL; + + static unsigned char key[AES_BLOCK]; + static unsigned char iv_buf[CHUNK_SIZE] __attribute__((aligned(128))); +@@ -533,9 +533,9 @@ void close_jitter_entropy_source(struct rng *ent_src) + close(pipefds[0]); + free(tdata); + free(threads); ++ free(aes_buf); + if (ossl_ctx) { + ossl_aes_exit(ossl_ctx); + ossl_ctx = NULL; + } + } +- +-- +2.26.3 + diff --git a/0009-Brush-up-rngd_nistbeacon.c.patch b/0009-Brush-up-rngd_nistbeacon.c.patch new file mode 100644 index 0000000..5ba2404 --- /dev/null +++ b/0009-Brush-up-rngd_nistbeacon.c.patch @@ -0,0 +1,233 @@ +From c87d4f8616c42a921cec37e8758e71f5651c727f Mon Sep 17 00:00:00 2001 +From: Vladis Dronov +Date: Mon, 14 Jun 2021 14:37:28 +0200 +Subject: Brush up rngd_nistbeacon.c + +1) Fix a possile NULL dereference in get_nist_record() and update_active_cert(). +It may happen in an unlikely case when curl_easy_setopt(CURLOPT_WRITEFUNCTION) +fails but curl_easy_perform() succeeds. + +Also adjust error handling and logging. This way a libcurl instance is properly +cleaned up in all cases. + +This fixes code for the following warnings. NULL pointer warning still stays, +as covscan does not recognize parse_nist_json_block() as a callback. + +Error: CHECKED_RETURN (CWE-252): [#def13] +rng-tools-6.12/rngd_nistbeacon.c:582: check_return: Calling "curl_easy_setopt(curl, +_curl_opt, certurl)" without checking return value. This library function may fail +and return an error code. + 581| certurl = strcat(certurl, block.certificateIdString); + 582|-> curl_easy_setopt(curl, CURLOPT_URL, certurl); + +Error: CLANG_WARNING: [#def19] +rng-tools-6.12/rngd_nistbeacon.c:622:32: warning[core.NonNullParamChecker]: Null +pointer passed to 1st parameter expecting 'nonnull' + 622|-> activeCertId = strndup(block.certificateId, be32toh(block.certificateIdLen)); + +2) Remove unused variables from parse_nist_json_block(). + +3) Fix a signedness warning for nist_rand_buf and block.signatureValue. + +Signed-off-by: Vladis Dronov +--- + rngd_nistbeacon.c | 109 +++++++++++++++++++++++++++++++--------------- + 1 file changed, 74 insertions(+), 35 deletions(-) + +diff --git a/rngd_nistbeacon.c b/rngd_nistbeacon.c +index 5d51d44..51e3458 100644 +--- a/rngd_nistbeacon.c ++++ b/rngd_nistbeacon.c +@@ -74,7 +74,7 @@ static int get_nist_record(struct rng *ent_src); + + static size_t nist_buf_avail = 0; + static size_t nist_buf_ptr = 0; +-static char nist_rand_buf[NIST_BUF_SIZE]; ++static unsigned char nist_rand_buf[NIST_BUF_SIZE]; + static char errbuf[120]; + int cfp; + +@@ -275,23 +275,18 @@ static void get_json_byte_array(json_t *parent, char *key, char **val, uint32_t + } + + /* +- * Note, I'm making the assumption that the entire xml block gets returned ++ * Note, I'm making the assumption that the entire xml block gets returned + * in a single call here, which I should fix + */ + static size_t parse_nist_json_block(char *ptr, size_t size, size_t nemb, void *userdata) + { + size_t idx; + json_t *jidx; +- xmlTextReaderPtr reader; +- int ret = 1; +- const char *name; +- size_t realsize = size * nemb; +- char *xml = (char *)ptr; +- json_t *json, *pulse, *values, *obj; ++ size_t realsize = size * nemb; ++ json_t *json, *pulse, *obj; + json_error_t jsonerror; + struct rng *ent_src = userdata; + +- + json = json_loads(ptr, size, &jsonerror); + if (!json) { + message_entsrc(ent_src,LOG_DAEMON|LOG_ERR, "Unparseable JSON\n"); +@@ -532,7 +527,8 @@ static int validate_nist_block(struct rng *ent_src) + goto out; + } + +- if (EVP_VerifyFinal(mdctx, block.signatureValue, be32toh(block.signatureValueLen), pubkey) < 1) { ++ if (EVP_VerifyFinal(mdctx, (unsigned char *)block.signatureValue, ++ be32toh(block.signatureValueLen), pubkey) < 1) { + unsigned long err; + message_entsrc(ent_src,LOG_DAEMON| LOG_ERR, "Unable to validate signature on message\n"); + while( (err = ERR_get_error()) != 0 ) { +@@ -566,7 +562,8 @@ static size_t copy_nist_certificate(char *ptr, size_t size, size_t nemb, void *u + return size * nemb; + } + +-static void update_active_cert() { ++static void update_active_cert(struct rng *ent_src) ++{ + CURL *curl; + CURLcode res; + char *certurl; +@@ -574,24 +571,46 @@ static void update_active_cert() { + + free(activeCert); + activeCert = NULL; +- ++ + curl = curl_easy_init(); +- if (!curl) ++ if (!curl) { ++ message_entsrc(ent_src, LOG_DAEMON|LOG_ERR, ++ "update_active_cert(): curl_easy_init() failed\n"); + return; ++ } + + certurl = alloca(urlsize); +- if (!certurl) +- return; ++ if (!certurl) { ++ message_entsrc(ent_src, LOG_DAEMON|LOG_ERR, ++ "update_active_cert(): alloca() failed\n"); ++ goto out_curl; ++ } + strcpy(certurl, NIST_CERT_BASE_URL); + certurl = strcat(certurl, block.certificateIdString); +- curl_easy_setopt(curl, CURLOPT_URL, certurl); +- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, copy_nist_certificate); ++ ++ res = curl_easy_setopt(curl, CURLOPT_URL, certurl); ++ if (res != CURLE_OK) { ++ message_entsrc(ent_src, LOG_DAEMON|LOG_ERR, ++ "update_active_cert(): curl_easy_setopt(URL) failed: %s\n", ++ curl_easy_strerror(res)); ++ goto out_curl; ++ } ++ res = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, copy_nist_certificate); ++ if (res != CURLE_OK) { ++ message_entsrc(ent_src, LOG_DAEMON|LOG_ERR, ++ "update_active_cert(): curl_easy_setopt(WRITEFUNC) failed: %s\n", ++ curl_easy_strerror(res)); ++ goto out_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)); +- } ++ if (res != CURLE_OK) { ++ message_entsrc(ent_src, LOG_DAEMON|LOG_ERR, ++ "update_active_cert(): curl_easy_perform() failed: %s\n", ++ curl_easy_strerror(res)); ++ } ++ ++out_curl: + curl_easy_cleanup(curl); + return; + } +@@ -603,42 +622,62 @@ static int get_nist_record(struct rng *ent_src) + int rc = 1; + + curl = curl_easy_init(); +- +- if (!curl) ++ if (!curl) { ++ message_entsrc(ent_src, LOG_DAEMON|LOG_ERR, ++ "get_nist_record(): curl_easy_init() failed\n"); + goto out; ++ } + +- curl_easy_setopt(curl, CURLOPT_URL, NIST_RECORD_URL); +- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, parse_nist_json_block); +- curl_easy_setopt(curl, CURLOPT_WRITEDATA, ent_src); ++ res = curl_easy_setopt(curl, CURLOPT_URL, NIST_RECORD_URL); ++ if (res != CURLE_OK) { ++ message_entsrc(ent_src, LOG_DAEMON|LOG_ERR, ++ "get_nist_record(): curl_easy_setopt(URL) failed: %s\n", ++ curl_easy_strerror(res)); ++ goto out_curl; ++ } ++ res = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, parse_nist_json_block); ++ if (res != CURLE_OK) { ++ message_entsrc(ent_src, LOG_DAEMON|LOG_ERR, ++ "get_nist_record(): curl_easy_setopt(WRITEFUNC) failed: %s\n", ++ curl_easy_strerror(res)); ++ goto out_curl; ++ } ++ res = curl_easy_setopt(curl, CURLOPT_WRITEDATA, ent_src); ++ if (res != CURLE_OK) { ++ message_entsrc(ent_src, LOG_DAEMON|LOG_ERR, ++ "get_nist_record(): curl_easy_setopt(WRITEDATA) failed: %s\n", ++ curl_easy_strerror(res)); ++ goto out_curl; ++ } + ++ /* parse_nist_json_block() runs here as a callback */ + res = curl_easy_perform(curl); + if (res != CURLE_OK) { +- fprintf(stderr, "curl_easy_perform() failed: %s\n", ++ message_entsrc(ent_src, LOG_DAEMON|LOG_ERR, ++ "get_nist_record(): curl_easy_perform() failed: %s\n", + curl_easy_strerror(res)); +- goto out; ++ goto out_curl; + } + +- 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)); +- update_active_cert(); ++ update_active_cert(ent_src); + } + + if (validate_nist_block(ent_src)) { +- message_entsrc(ent_src,LOG_DAEMON|LOG_ERR, "Received block failed validation\n"); +- goto out; ++ message_entsrc(ent_src, LOG_DAEMON|LOG_ERR, "Received block failed validation\n"); ++ goto out_curl; + } + +- + rc = 0; + ++out_curl: ++ curl_easy_cleanup(curl); + out: + return rc; +- + } + + /* +-- +2.26.3 + diff --git a/rng-tools-1-Improve-rngd-console-output-readability.patch b/rng-tools-1-Improve-rngd-console-output-readability.patch deleted file mode 100644 index 28a1a4f..0000000 --- a/rng-tools-1-Improve-rngd-console-output-readability.patch +++ /dev/null @@ -1,33 +0,0 @@ -From d989f5690037eb2162eeea7352a7f8eeecc7989b Mon Sep 17 00:00:00 2001 -From: Nikolai Kostrigin -Date: Fri, 12 Mar 2021 15:11:42 +0300 -Subject: Improve rngd console output readability - -Prevent messing "None" status message with next section header: -"[...] -Entropy sources that are available but disabled -NoneAvailable and enabled entropy sources: -4: NIST Network Entropy Beacon (nist) -[...]" - -Signed-off-by: Nikolai Kostrigin ---- - rngd.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/rngd.c b/rngd.c -index c770259..7d31e68 100644 ---- a/rngd.c -+++ b/rngd.c -@@ -860,7 +860,7 @@ int main(int argc, char **argv) - entropy_sources[i].failed_init = false; - } - if (!found) -- message(LOG_CONS|LOG_INFO, "None"); -+ message(LOG_CONS|LOG_INFO, "None\n"); - msg_squash = true; - } else - message(LOG_DAEMON|LOG_INFO, "Initializing available sources\n"); --- -2.26.3 - diff --git a/rng-tools-2-try-to-build-with-rtlsdr-by-default.patch b/rng-tools-2-try-to-build-with-rtlsdr-by-default.patch deleted file mode 100644 index 7e7a644..0000000 --- a/rng-tools-2-try-to-build-with-rtlsdr-by-default.patch +++ /dev/null @@ -1,26 +0,0 @@ -From e00e2155ad04f8b3a964fd482bddd8c27b5b9999 Mon Sep 17 00:00:00 2001 -From: Jan Palus -Date: Tue, 4 May 2021 23:50:47 +0200 -Subject: try to build with rtlsdr by default - -Fixes #125 ---- - configure.ac | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/configure.ac b/configure.ac -index 0e04cb8..c4f15d4 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -45,7 +45,7 @@ AC_ARG_WITH([rtlsdr], - AS_HELP_STRING([--without-rtlsdr], - [Disable rtlsdr support. ]), - [], -- [with_rtlsdr=no] -+ [with_rtlsdr=check] - ) - - AC_ARG_WITH([libargp], --- -2.26.3 - diff --git a/rng-tools-3-Create-helpers-for-openssl-AES-use.patch b/rng-tools-3-Create-helpers-for-openssl-AES-use.patch deleted file mode 100644 index 537b509..0000000 --- a/rng-tools-3-Create-helpers-for-openssl-AES-use.patch +++ /dev/null @@ -1,864 +0,0 @@ -From 0f0580f3ae98fecf41de4a0346f5e11f390418b7 Mon Sep 17 00:00:00 2001 -From: Benjamin Herrenschmidt -Date: Fri, 21 May 2021 13:46:42 +1000 -Subject: Create helpers for openssl AES use - -This moves the openssl code that is duplicated in several sources -to some helpers. This also fixes the use of "strlen" on raw random -data which probably didn't do what someone thought it did ... - -Signed-off-by: Benjamin Herrenschmidt ---- - Makefile.am | 2 +- - ossl_helpers.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++ - ossl_helpers.h | 58 ++++++++++++++++++++++ - rngd_darn.c | 90 +++++----------------------------- - rngd_jitter.c | 73 +++------------------------ - rngd_nistbeacon.c | 84 ++++++------------------------- - rngd_rdrand.c | 93 +++++------------------------------ - rngd_rtlsdr.c | 54 +++++++------------- - 8 files changed, 246 insertions(+), 330 deletions(-) - create mode 100644 ossl_helpers.c - create mode 100644 ossl_helpers.h - -diff --git a/Makefile.am b/Makefile.am -index fbeff32..6f938bc 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -9,7 +9,7 @@ man_MANS = rngd.8 rngtest.1 - noinst_LIBRARIES = librngd.a - - rngd_SOURCES = rngd.h rngd.c rngd_entsource.h rngd_entsource.c \ -- rngd_linux.h rngd_linux.c util.c -+ rngd_linux.h rngd_linux.c util.c ossl_helpers.c - - if NISTBEACON - rngd_SOURCES += rngd_nistbeacon.c -diff --git a/ossl_helpers.c b/ossl_helpers.c -new file mode 100644 -index 0000000..c3c1fbb ---- /dev/null -+++ b/ossl_helpers.c -@@ -0,0 +1,122 @@ -+/* -+ * ossl_helpers.c -- Helper wrappers around openssl functions -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "ossl_helpers.h" -+ -+#include -+#include -+#include -+ -+struct ossl_aes_ctx -+{ -+ EVP_CIPHER_CTX *c; -+ const unsigned char *key; -+ const unsigned char *iv; -+}; -+ -+void ossl_aes_random_key(unsigned char *key, const unsigned char *pepper) -+{ -+ static unsigned char default_key[AES_BLOCK] = { -+ 0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70, -+ 0x80,0x90,0xa0,0xb0,0xc0,0xd0,0xe0,0xf0 -+ }; /* AES data reduction key */ -+ unsigned char stack_junk[AES_BLOCK]; -+ int fd, i; -+ -+ /* Try getting some randomness from the kernel */ -+ fd = open("/dev/urandom", O_RDONLY); -+ if (fd >= 0) { -+ int r = read(fd, key, sizeof key); -+ close(fd); -+ } -+ -+ /* Mix in our default key */ -+ for (i = 0; i < AES_BLOCK && pepper; i++) -+ key[i] ^= default_key[i]; -+ -+ /* Mix in stack junk */ -+ for (i = 0; i < AES_BLOCK && pepper; i++) -+ key[i] ^= stack_junk[i]; -+ -+ /* Spice it up if we can */ -+ for (i = 0; i < AES_BLOCK && pepper; i++) -+ key[i] ^= pepper[i]; -+} -+ -+ -+struct ossl_aes_ctx *ossl_aes_init(const unsigned char *key, -+ const unsigned char *iv) -+{ -+ struct ossl_aes_ctx *ctx; -+ -+ ctx = malloc(sizeof(*ctx)); -+ if (!ctx) -+ return NULL; -+ -+ ctx->c = EVP_CIPHER_CTX_new(); -+ if (!ctx->c) { -+ free(ctx); -+ return NULL; -+ } -+ ctx->key = key; -+ ctx->iv = iv; -+ return ctx; -+} -+ -+void ossl_aes_exit(struct ossl_aes_ctx *ctx) -+{ -+ EVP_CIPHER_CTX_free(ctx->c); -+ free(ctx); -+} -+ -+int ossl_aes_encrypt(struct ossl_aes_ctx *ctx, -+ unsigned char *plaintext, int plaintext_len, -+ unsigned char *ciphertext) -+{ -+ int len, ciphertext_len; -+ -+ if(1 != EVP_EncryptInit_ex(ctx->c, EVP_aes_128_cbc(), NULL, ctx->key, ctx->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->c, 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->c, ciphertext + len, &len)) -+ return 0; -+ ciphertext_len += len; -+ -+ return ciphertext_len; -+} -+ -diff --git a/ossl_helpers.h b/ossl_helpers.h -new file mode 100644 -index 0000000..e21e331 ---- /dev/null -+++ b/ossl_helpers.h -@@ -0,0 +1,58 @@ -+/* -+ * ossl_helpers.h -- Helper wrappers around openssl functions -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA -+ */ -+ -+#ifndef OSSL_HELPERS__H -+#define OSSL_HELPERS__H -+ -+#define AES_BLOCK 16 -+ -+struct ossl_aes_ctx; -+ -+extern int ossl_aes_encrypt(struct ossl_aes_ctx *ctx, -+ unsigned char *plaintext, int plaintext_len, -+ unsigned char *ciphertext); -+ -+extern struct ossl_aes_ctx *ossl_aes_init(const unsigned char *key, -+ const unsigned char *iv); -+extern void ossl_aes_exit(struct ossl_aes_ctx *ctx); -+extern void ossl_aes_random_key(unsigned char *key, const unsigned char *pepper); -+ -+static inline int ossl_aes_mangle(struct ossl_aes_ctx *ctx, unsigned char *data, -+ size_t size) -+{ -+ 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. -+ * -+ * For AES, one extra AES block should be sufficient. -+ */ -+ unsigned char ciphertext[size + AES_BLOCK]; -+ -+ /* Encrypt the plaintext */ -+ ciphertext_len = ossl_aes_encrypt(ctx, data, size, ciphertext); -+ if (!ciphertext_len) -+ return -1; -+ -+ memcpy(data, ciphertext, size); -+ return ciphertext_len; -+} -+ -+#endif /* OSSL_HELPERS__H */ -diff --git a/rngd_darn.c b/rngd_darn.c -index f6b9cd4..bc8edec 100644 ---- a/rngd_darn.c -+++ b/rngd_darn.c -@@ -29,15 +29,12 @@ - #include - #include - #include --#include --#include --#include -- - - #include "rngd.h" - #include "fips.h" - #include "exits.h" - #include "rngd_entsource.h" -+#include "ossl_helpers.h" - - #define min(x,y) ({ \ - typeof(x) _x = (x); \ -@@ -49,18 +46,13 @@ static uint64_t get_darn(); - 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 - #define CHUNK_SIZE AES_BLOCK * 8 - #define RDRAND_ROUNDS 512 /* 512:1 data reduction */ -- --static unsigned char key[AES_BLOCK] = { -- 0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70, -- 0x80,0x90,0xa0,0xb0,0xc0,0xd0,0xe0,0xf0 --}; /* AES data reduction key */ -- - #define THRESH_BITS 14 - --static EVP_CIPHER_CTX *ctx = NULL; -+/* ossl AES context */ -+static struct ossl_aes_ctx *ossl_ctx; -+static unsigned char key[AES_BLOCK]; - static unsigned char iv_buf[AES_BLOCK]; - - static unsigned char darn_rand_buf[CHUNK_SIZE]; -@@ -72,15 +64,10 @@ static size_t rand_bytes_served = 0; - - static int init_openssl(struct rng *ent_src) - { -- unsigned char xkey[AES_BLOCK]; -- int i; - uint64_t darn_val; -+ int i; - -- /* -- * Use stack junk to create a key, shuffle it a bit -- */ -- for (i=0; i< sizeof(key); i++) -- key[i] ^= xkey[i]; -+ ossl_aes_random_key(key, NULL); - - darn_val = get_darn(); - if (darn_val == ULONG_MAX) -@@ -92,13 +79,11 @@ static int init_openssl(struct rng *ent_src) - return 1; - memcpy(&iv_buf[8], &darn_val, sizeof(uint64_t)); - -- if (ctx != NULL) { -- /* Clean up */ -- EVP_CIPHER_CTX_free(ctx); -- } -- if(!(ctx = EVP_CIPHER_CTX_new())) -- return 1; -- -+ if (ossl_ctx != NULL) -+ ossl_aes_exit(ossl_ctx); -+ ossl_ctx = ossl_aes_init(key, iv_buf); -+ if (!ossl_ctx) -+ return 1; - rand_bytes_served = 0; - if (refill_rand(ent_src, false)) - return 1; -@@ -109,56 +94,6 @@ static int init_openssl(struct rng *ent_src) - return 0; - } - --static int osslencrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key, -- unsigned char *iv, unsigned char *ciphertext) --{ -- int len; -- -- int ciphertext_len; -- -- 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; -- -- return ciphertext_len; --} -- --static inline int openssl_mangle(unsigned char *tmp, size_t size, struct rng *ent_src) --{ -- 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]; -- -- /* 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, bool allow_reinit) - { - int i; -@@ -172,9 +107,8 @@ static int refill_rand(struct rng *ent_src, bool allow_reinit) - return 1; - } - -- if (openssl_mangle(darn_rand_buf, CHUNK_SIZE, ent_src)) { -+ if (ossl_aes_mangle(ossl_ctx, darn_rand_buf, CHUNK_SIZE) < 0) - return 1; -- } - } else { - uint64_t *ptr = (uint64_t *)darn_rand_buf; - for (i = 0; i < CHUNK_SIZE/sizeof(uint64_t); i++) { -diff --git a/rngd_jitter.c b/rngd_jitter.c -index c803f0d..133c7e4 100644 ---- a/rngd_jitter.c -+++ b/rngd_jitter.c -@@ -27,9 +27,6 @@ - #include - #include - #include --#include --#include --#include - - #include "rng-tools-config.h" - -@@ -39,9 +36,9 @@ - #include "fips.h" - #include "exits.h" - #include "rngd_entsource.h" -+#include "ossl_helpers.h" - - /* Read data from the drng in chunks of 128 bytes for AES scrambling */ --#define AES_BLOCK 16 - #define CHUNK_SIZE (AES_BLOCK*8) /* 8 parallel streams */ - #define RDRAND_ROUNDS 512 /* 512:1 data reduction */ - -@@ -71,65 +68,7 @@ unsigned char *aes_buf; - - static char key[AES_BLOCK]; - static unsigned char iv_buf[CHUNK_SIZE] __attribute__((aligned(128))); -- --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, struct rng *ent_src) --{ -- 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]; -- -- /* Encrypt the plaintext */ -- ciphertext_len = osslencrypt (tmp, strlen(tmp), key, iv_buf, -- ciphertext); -- if (!ciphertext_len) -- return -1; -- -- memcpy(tmp, ciphertext, strlen(tmp)); -- return 0; --} -+static struct ossl_aes_ctx *ossl_ctx; - - int xread_jitter(void *buf, size_t size, struct rng *ent_src) - { -@@ -152,7 +91,7 @@ try_again: - while(need) { - request = (need >= current->buf_sz) ? current->buf_sz : need; - memcpy(buf, &aes_buf[total], request); -- openssl_mangle(aes_buf, ent_src); -+ ossl_aes_mangle(ossl_ctx, aes_buf, request); - need -= request; - total += request; - } -@@ -462,6 +401,7 @@ int init_jitter_entropy_source(struct rng *ent_src) - } else { - /* re-enable AES */ - ent_src->rng_options[JITTER_OPT_USE_AES].int_val = 1; -+ ossl_ctx = ossl_aes_init(key, iv_buf); - } - xread_jitter(aes_buf, tdata[0].buf_sz, ent_src); - } else { -@@ -511,6 +451,9 @@ void close_jitter_entropy_source(struct rng *ent_src) - close(pipefds[0]); - free(tdata); - free(threads); -- return; -+ if (ossl_ctx) { -+ ossl_aes_exit(ossl_ctx); -+ ossl_ctx = NULL; -+ } - } - -diff --git a/rngd_nistbeacon.c b/rngd_nistbeacon.c -index 5195d33..5d51d44 100644 ---- a/rngd_nistbeacon.c -+++ b/rngd_nistbeacon.c -@@ -56,6 +56,7 @@ - #include "fips.h" - #include "exits.h" - #include "rngd_entsource.h" -+#include "ossl_helpers.h" - - #define NIST_RECORD_URL "https://beacon.nist.gov/beacon/2.0/pulse/last" - #define NIST_CERT_BASE_URL "https://beacon.nist.gov/beacon/2.0/certificate/" -@@ -133,75 +134,11 @@ X509 *cert = NULL; - EVP_PKEY *pubkey; - 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 unsigned char mangle_key[AES_BLOCK]; -+static unsigned char mangle_iv_buf[CHUNK_SIZE]; -+static struct ossl_aes_ctx *ossl_ctx; - - static int refill_rand(struct rng *ent_src) - { -@@ -220,7 +157,7 @@ static int refill_rand(struct rng *ent_src) - } - 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) { -+ if (ossl_aes_mangle(ossl_ctx, nist_rand_buf, NIST_BUF_SIZE) < 0) { - message_entsrc(ent_src, LOG_DAEMON|LOG_DEBUG, "Failed mangle\n"); - return 1; - } -@@ -712,6 +649,17 @@ int init_nist_entropy_source(struct rng *ent_src) - int rc; - memset(&block, 0, sizeof (struct nist_data_block)); - -+ if (ent_src->rng_options[NIST_OPT_USE_AES].int_val) { -+ unsigned char *p; -+ int i; -+ -+ ossl_aes_random_key(mangle_key, NULL); -+ for (i = 0, p = mangle_iv_buf; i < 8; i++, p += AES_BLOCK) -+ ossl_aes_random_key(p, NULL); -+ -+ ossl_ctx = ossl_aes_init(mangle_key, mangle_iv_buf); -+ } -+ - rc = refill_rand(ent_src); - if (!rc) { - message_entsrc(ent_src,LOG_DAEMON|LOG_WARNING, "WARNING: NIST Randomness beacon " -diff --git a/rngd_rdrand.c b/rngd_rdrand.c -index b1f597c..cba27a9 100644 ---- a/rngd_rdrand.c -+++ b/rngd_rdrand.c -@@ -37,24 +37,22 @@ - #include - #include - #include --#include --#include --#include - - #include "rngd.h" - #include "fips.h" - #include "exits.h" - #include "rngd_entsource.h" -+#include "ossl_helpers.h" - - /* Read data from the drng in chunks of 128 bytes for AES scrambling */ --#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] = { -- 0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70, -- 0x80,0x90,0xa0,0xb0,0xc0,0xd0,0xe0,0xf0 --}; /* AES data reduction key */ -+/* AES data reduction key */ -+static unsigned char key[AES_BLOCK]; -+ -+/* ossl AES context */ -+static struct ossl_aes_ctx *ossl_ctx; - - /* Struct for CPUID return values */ - struct cpuid { -@@ -142,65 +140,6 @@ static void cpuid(unsigned int leaf, unsigned int subleaf, struct cpuid *out) - static unsigned char iv_buf[CHUNK_SIZE] __attribute__((aligned(128))); - static int have_aesni, have_rdseed; - --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, struct rng *ent_src) --{ -- 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]; -- -- /* Encrypt the plaintext */ -- ciphertext_len = osslencrypt (tmp, strlen(tmp), key, iv_buf, -- ciphertext); -- if (!ciphertext_len) -- return -1; -- -- memcpy(tmp, ciphertext, strlen(tmp)); -- return 0; --} -- - int xread_drng_with_aes(void *buf, size_t size, struct rng *ent_src) - { - static unsigned char rdrand_buf[CHUNK_SIZE * RDRAND_ROUNDS] -@@ -227,7 +166,7 @@ int xread_drng_with_aes(void *buf, size_t size, struct rng *ent_src) - x86_aes_mangle(rdrand_buf, iv_buf); - data = iv_buf; - chunk = CHUNK_SIZE; -- } else if (!openssl_mangle(rdrand_buf, ent_src)) { -+ } else if (ossl_aes_mangle(ossl_ctx, rdrand_buf, AES_BLOCK) >= 0) { - data = rdrand_buf + - AES_BLOCK * (RDRAND_ROUNDS - 1); - chunk = AES_BLOCK; -@@ -288,9 +227,6 @@ int xread_drng(void *buf, size_t size, struct rng *ent_src) - - static int init_aesni(const void *key) - { -- if (!have_aesni) -- return 1; -- - x86_aes_expand_key(key); - return 0; - } -@@ -335,21 +271,16 @@ int init_drng_entropy_source(struct rng *ent_src) - /* Randomize the AES data reduction key the best we can */ - if (x86_rdrand_bytes(xkey, sizeof xkey) != sizeof xkey) - return 1; -- -- fd = open("/dev/urandom", O_RDONLY); -- if (fd >= 0) { -- read(fd, key, sizeof key); -- close(fd); -- } -- -- for (i = 0; i < (int)sizeof key; i++) -- key[i] ^= xkey[i]; -+ ossl_aes_random_key(key, xkey); - - /* Initialize the IV buffer */ - if (x86_rdrand_bytes(iv_buf, CHUNK_SIZE) != CHUNK_SIZE) - return 1; - -- init_aesni(key); -+ if (have_aesni) -+ init_aesni(key); -+ else -+ ossl_ctx = ossl_aes_init(key, iv_buf); - - if (have_rdseed) - message_entsrc(ent_src,LOG_DAEMON|LOG_INFO, "Enabling RDSEED rng support\n"); -diff --git a/rngd_rtlsdr.c b/rngd_rtlsdr.c -index 73046cd..949c8b0 100644 ---- a/rngd_rtlsdr.c -+++ b/rngd_rtlsdr.c -@@ -19,11 +19,11 @@ - #include - - #include "rngd.h" -+#include "ossl_helpers.h" - - #define RAW_BUF_SZ 4096 - - #define CHUNK_SIZE (AES_BLOCK*8) /* 8 parallel streams */ --#define AES_BLOCK 16 - - static rtlsdr_dev_t *radio = NULL; - static char raw_buffera[RAW_BUF_SZ]; -@@ -33,6 +33,12 @@ static int sample_min; - static int sample_max; - static int gain = 200; - -+/* AES data reduction key */ -+static unsigned char key[AES_BLOCK]; -+static unsigned char iv[CHUNK_SIZE]; -+static struct ossl_aes_ctx *ossl_ctx; -+ -+ - static int get_random_freq() - { - int range = freq_max - freq_min; -@@ -97,7 +103,13 @@ int init_rtlsdr_entropy_source(struct rng *ent_src) - message_entsrc(ent_src, LOG_DAEMON, "%d: %s %s\n", i, vendor, product); - } - -- /* -+ ossl_ctx = ossl_aes_init(key, iv); -+ if (!ossl_ctx) { -+ message_entsrc(ent_src, LOG_DAEMON, "Failed to setup openssl\n"); -+ return 1; -+ } -+ -+ /* - * Get our default sample rate and freq settings, as well as the devid - * to use - */ -@@ -144,51 +156,19 @@ void close_rtlsdr_entropy_source(struct rng *ent_src) - { - if (radio) - rtlsdr_close(radio); -- return; -+ if (ossl_ctx) -+ ossl_aes_exit(ossl_ctx); - } - - static size_t condition_buffer(unsigned char *in, unsigned char *out, size_t insize, size_t outsize) - { -- EVP_CIPHER_CTX *ctx; -- static unsigned char key[AES_BLOCK]; -- unsigned char iv[CHUNK_SIZE] __attribute__((aligned(128))); -- int len; -- size_t ciphertext_len = 0; -- - /* - * Setup our key and iv - */ - memcpy(key, in, AES_BLOCK); - memcpy(iv, &in[AES_BLOCK], CHUNK_SIZE); - -- /* 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)) -- goto out; -- /* -- * 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, out, &len, in, insize)) -- goto out; -- -- ciphertext_len = len; -- -- /* -- * Finalise the encryption. Further ciphertext bytes may be written at -- * this stage. -- */ -- if(1 != EVP_EncryptFinal_ex(ctx, out, &len)) -- return 0; -- ciphertext_len += len; -- --out: -- /* Clean up */ -- EVP_CIPHER_CTX_free(ctx); -- -- return ciphertext_len; -+ return ossl_aes_encrypt(ossl_ctx, in, insize, out); - } - - int xread_rtlsdr(void *buf, size_t size, struct rng *ent_src) --- -2.26.3 - diff --git a/rng-tools.spec b/rng-tools.spec index 8b6f588..b5f33a6 100644 --- a/rng-tools.spec +++ b/rng-tools.spec @@ -10,8 +10,8 @@ Summary: Random number generator related utilities Name: rng-tools -Version: 6.12 -Release: 5%{?dist} +Version: 6.13 +Release: 1%{?dist} License: GPLv2+ URL: https://github.com/nhorman/rng-tools Source0: https://github.com/nhorman/rng-tools/archive/v%{version}/rng-tools-%{version}.tar.gz @@ -37,11 +37,15 @@ BuildRequires: libp11-devel Requires(post): systemd Requires(preun): systemd Requires(postun): systemd -Provides: jitterentropy-rngd -Patch1: rng-tools-1-Improve-rngd-console-output-readability.patch -Patch2: rng-tools-2-try-to-build-with-rtlsdr-by-default.patch -Patch3: rng-tools-3-Create-helpers-for-openssl-AES-use.patch +Patch1: 0001-Use-AM_PROG_AR-over-AC_CHECK_TOOLS.patch +Patch2: 0003-AC_CANONICAL_TARGET-AC_CANONICAL_HOST.patch +Patch3: 0004-Fix-logic-in-ossl_aes_random_key.patch +Patch4: 0005-Fix-a-read-returning-zero-case-in-init_entropy_sourc.patch +Patch5: 0006-Fix-minor-possibilities-of-using-a-NULL-pointer.patch +Patch6: 0007-Small-bug-and-warning-fixes-per-covscan-report.patch +Patch7: 0008-Fix-a-minor-memory-leak-in-rngd_jitter.c.patch +Patch8: 0009-Brush-up-rngd_nistbeacon.c.patch %description Hardware random number generation tools. @@ -95,6 +99,11 @@ udevadm trigger --sysname-match=hw_random --settle %attr(0644,root,root) %{_udevrulesdir}/60-hwrng.rules %changelog +* Wed Jun 16 2021 Vladis Dronov - 6.13-1 +- Update the sources to 6.13 +- Add important fixes from the upstream +- Remove Provides: jitterentropy-rngd as it was retired in f29. + * Wed Jun 16 2021 Mohan Boddu - 6.12-5 - Rebuilt for RHEL 9 BETA for openssl 3.0 Related: rhbz#1971065 @@ -193,7 +202,7 @@ udevadm trigger --sysname-match=hw_random --settle - update to latest upstream (#1598608) * Thu May 10 2018 Neil Horman -- Update to latest upstream +- Update to latest upstream * Thu Feb 15 2018 Adam Williamson - 6.1-4 - Drop all attempts to 'fix' #1490632, revert spec to same as 6.1-1 diff --git a/sources b/sources index 84876d4..ccf1456 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (rng-tools-6.12.tar.gz) = 56dd334b65dcec1456f8dbdbee5d83590de27cb6ee1b7715828b5316a913557fd178e264139dc92a82e09635ca15b1eb5f6169bfb4412fbe1b06ea28a5064c64 +SHA512 (rng-tools-6.13.tar.gz) = def5f2dcdd1771e8fe5af9476de866ff89a225065416672165af6019cbb166f874fae936b3705221aa47dc13ae99fa63d054d7d49b612f3151cd922a0a129490