Skip to content

Commit

Permalink
char/lrng: sysctls and /proc interface
Browse files Browse the repository at this point in the history
The LRNG sysctl interface provides the same controls as the existing
/dev/random implementation. These sysctls behave identically and are
implemented identically. The goal is to allow a possible merge of the
existing /dev/random implementation with this implementation which
implies that this patch tries have a very close similarity. Yet, all
sysctls are documented at [1].

In addition, it provides the file lrng_type which provides details about
the LRNG:

- the name of the DRNG that produces the random numbers for /dev/random,
/dev/urandom, getrandom(2)

- the hash used to produce random numbers from the entropy pool

- the number of secondary DRNG instances

- indicator whether the LRNG operates SP800-90B compliant

- indicator whether a high-resolution timer is identified - only with a
high-resolution timer the interrupt noise source will deliver sufficient
entropy

- indicator whether the LRNG has been minimally seeded (i.e. is the
secondary DRNG seeded with at least 128 bits of entropy)

- indicator whether the LRNG has been fully seeded (i.e. is the
secondary DRNG seeded with at least 256 bits of entropy)

[1] https://www.chronox.de/lrng.html

CC: Torsten Duwe <duwe@lst.de>
CC: "Eric W. Biederman" <ebiederm@xmission.com>
CC: "Alexander E. Patrakov" <patrakov@gmail.com>
CC: "Ahmed S. Darwish" <darwish.07@gmail.com>
CC: "Theodore Y. Ts'o" <tytso@mit.edu>
CC: Willy Tarreau <w@1wt.eu>
CC: Matthew Garrett <mjg59@srcf.ucam.org>
CC: Vito Caputo <vcaputo@pengaru.com>
CC: Andreas Dilger <adilger.kernel@dilger.ca>
CC: Jan Kara <jack@suse.cz>
CC: Ray Strode <rstrode@redhat.com>
CC: William Jon McCann <mccann@jhu.edu>
CC: zhangjs <zachary@baishancloud.com>
CC: Andy Lutomirski <luto@kernel.org>
CC: Florian Weimer <fweimer@redhat.com>
CC: Lennart Poettering <mzxreary@0pointer.de>
CC: Nicolai Stange <nstange@suse.de>
CC: Alexander Lobakin <alobakin@mailbox.org>
Reviewed-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Reviewed-by: Roman Drahtmueller <draht@schaltsekun.de>
Tested-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Tested-by: Neil Horman <nhorman@redhat.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
  • Loading branch information
smuellerDD authored and xanmod committed Jul 19, 2021
1 parent 056bcf3 commit 79cbad5
Show file tree
Hide file tree
Showing 4 changed files with 190 additions and 2 deletions.
1 change: 1 addition & 0 deletions drivers/char/lrng/Makefile
Expand Up @@ -9,3 +9,4 @@ obj-y += lrng_pool.o lrng_aux.o \
lrng_interfaces.o

obj-$(CONFIG_NUMA) += lrng_numa.o
obj-$(CONFIG_SYSCTL) += lrng_proc.o
2 changes: 0 additions & 2 deletions drivers/char/lrng/lrng_interfaces.c
Expand Up @@ -38,8 +38,6 @@ static DECLARE_WAIT_QUEUE_HEAD(lrng_write_wait);
static DECLARE_WAIT_QUEUE_HEAD(lrng_init_wait);
static struct fasync_struct *fasync;

struct ctl_table random_table[];

/********************************** Helper ***********************************/

/* Is the DRNG seed level too low? */
Expand Down
4 changes: 4 additions & 0 deletions drivers/char/lrng/lrng_internal.h
Expand Up @@ -114,7 +114,11 @@ void lrng_cc20_init_state(struct chacha20_state *state);

/********************************** /proc *************************************/

#ifdef CONFIG_SYSCTL
void lrng_pool_inc_numa_node(void);
#else
static inline void lrng_pool_inc_numa_node(void) { }
#endif

/****************************** LRNG interfaces *******************************/

Expand Down
185 changes: 185 additions & 0 deletions drivers/char/lrng/lrng_proc.c
@@ -0,0 +1,185 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
/*
* LRNG proc and sysctl interfaces
*
* Copyright (C) 2016 - 2021, Stephan Mueller <smueller@chronox.de>
*/

#include <linux/lrng.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/sysctl.h>
#include <linux/uuid.h>

#include "lrng_internal.h"
#include "lrng_sw_noise.h"

/*
* This function is used to return both the bootid UUID, and random
* UUID. The difference is in whether table->data is NULL; if it is,
* then a new UUID is generated and returned to the user.
*
* If the user accesses this via the proc interface, the UUID will be
* returned as an ASCII string in the standard UUID format; if via the
* sysctl system call, as 16 bytes of binary data.
*/
static int lrng_proc_do_uuid(struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct ctl_table fake_table;
unsigned char buf[64], tmp_uuid[16], *uuid;

uuid = table->data;
if (!uuid) {
uuid = tmp_uuid;
generate_random_uuid(uuid);
} else {
static DEFINE_SPINLOCK(bootid_spinlock);

spin_lock(&bootid_spinlock);
if (!uuid[8])
generate_random_uuid(uuid);
spin_unlock(&bootid_spinlock);
}

sprintf(buf, "%pU", uuid);

fake_table.data = buf;
fake_table.maxlen = sizeof(buf);

return proc_dostring(&fake_table, write, buffer, lenp, ppos);
}

static int lrng_proc_do_entropy(struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct ctl_table fake_table;
int entropy_count;

entropy_count = lrng_avail_entropy();

fake_table.data = &entropy_count;
fake_table.maxlen = sizeof(entropy_count);

return proc_dointvec(&fake_table, write, buffer, lenp, ppos);
}

static int lrng_proc_do_poolsize(struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct ctl_table fake_table;
int entropy_count;

/* LRNG can at most retain entropy in per-CPU pools and aux pool */
entropy_count = lrng_get_digestsize() + lrng_pcpu_avail_pool_size();

fake_table.data = &entropy_count;
fake_table.maxlen = sizeof(entropy_count);

return proc_dointvec(&fake_table, write, buffer, lenp, ppos);
}

static int lrng_min_write_thresh;
static int lrng_max_write_thresh = LRNG_MAX_DIGESTSIZE;
static char lrng_sysctl_bootid[16];
static int lrng_drng_reseed_max_min;

struct ctl_table random_table[] = {
{
.procname = "poolsize",
.maxlen = sizeof(int),
.mode = 0444,
.proc_handler = lrng_proc_do_poolsize,
},
{
.procname = "entropy_avail",
.maxlen = sizeof(int),
.mode = 0444,
.proc_handler = lrng_proc_do_entropy,
},
{
.procname = "write_wakeup_threshold",
.data = &lrng_write_wakeup_bits,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec_minmax,
.extra1 = &lrng_min_write_thresh,
.extra2 = &lrng_max_write_thresh,
},
{
.procname = "boot_id",
.data = &lrng_sysctl_bootid,
.maxlen = 16,
.mode = 0444,
.proc_handler = lrng_proc_do_uuid,
},
{
.procname = "uuid",
.maxlen = 16,
.mode = 0444,
.proc_handler = lrng_proc_do_uuid,
},
{
.procname = "urandom_min_reseed_secs",
.data = &lrng_drng_reseed_max_time,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec,
.extra1 = &lrng_drng_reseed_max_min,
},
{ }
};

/* Number of online DRNGs */
static u32 numa_drngs = 1;

void lrng_pool_inc_numa_node(void)
{
numa_drngs++;
}

static int lrng_proc_type_show(struct seq_file *m, void *v)
{
struct lrng_drng *lrng_drng_init = lrng_drng_init_instance();
unsigned long flags = 0;
unsigned char buf[390];

lrng_drng_lock(lrng_drng_init, &flags);
snprintf(buf, sizeof(buf),
"DRNG name: %s\n"
"Hash for reading entropy pool: %s\n"
"Hash for operating aux entropy pool: %s\n"
"LRNG security strength in bits: %d\n"
"per-CPU interrupt collection size: %u\n"
"number of DRNG instances: %u\n"
"Standards compliance: %s%s\n"
"High-resolution timer: %s\n"
"LRNG minimally seeded: %s\n"
"LRNG fully seeded: %s\n"
"Continuous compression: %s\n",
lrng_drng_init->crypto_cb->lrng_drng_name(),
lrng_drng_init->crypto_cb->lrng_hash_name(),
lrng_drng_init->crypto_cb->lrng_hash_name(),
lrng_security_strength(),
LRNG_DATA_NUM_VALUES,
numa_drngs,
lrng_sp80090b_compliant() ? "SP800-90B " : "",
lrng_sp80090c_compliant() ? "SP800-90C " : "",
lrng_pool_highres_timer() ? "true" : "false",
lrng_state_min_seeded() ? "true" : "false",
lrng_state_fully_seeded() ? "true" : "false",
lrng_pcpu_continuous_compression_state() ? "true" : "false");
lrng_drng_unlock(lrng_drng_init, &flags);

seq_write(m, buf, strlen(buf));

return 0;
}

static int __init lrng_proc_type_init(void)
{
proc_create_single("lrng_type", 0444, NULL, &lrng_proc_type_show);
return 0;
}

module_init(lrng_proc_type_init);

0 comments on commit 79cbad5

Please sign in to comment.