summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/rndpseudo.c316
-rw-r--r--sys/kern/kern_rndq.c315
-rw-r--r--sys/sys/rnd.h7
3 files changed, 323 insertions, 315 deletions
diff --git a/sys/dev/rndpseudo.c b/sys/dev/rndpseudo.c
index b54bc5c6329..d9d0ba86c23 100644
--- a/sys/dev/rndpseudo.c
+++ b/sys/dev/rndpseudo.c
@@ -1,4 +1,4 @@
-/* $NetBSD: rndpseudo.c,v 1.30 2015/04/14 12:27:02 riastradh Exp $ */
+/* $NetBSD: rndpseudo.c,v 1.31 2015/04/14 12:51:30 riastradh Exp $ */
/*-
* Copyright (c) 1997-2013 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rndpseudo.c,v 1.30 2015/04/14 12:27:02 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rndpseudo.c,v 1.31 2015/04/14 12:51:30 riastradh Exp $");
#if defined(_KERNEL_OPT)
#include "opt_compat_netbsd.h"
@@ -63,9 +63,6 @@ __KERNEL_RCSID(0, "$NetBSD: rndpseudo.c,v 1.30 2015/04/14 12:27:02 riastradh Exp
#include <sys/rnd.h>
#include <sys/rndpool.h>
#include <sys/rndsource.h>
-#ifdef COMPAT_50
-#include <compat/sys/rnd.h>
-#endif
#include <dev/rnd_private.h>
@@ -498,322 +495,17 @@ rnd_write(struct file *fp, off_t *offp, struct uio *uio,
return (ret);
}
-static void
-krndsource_to_rndsource(krndsource_t *kr, rndsource_t *r)
-{
- memset(r, 0, sizeof(*r));
- strlcpy(r->name, kr->name, sizeof(r->name));
- r->total = kr->total;
- r->type = kr->type;
- r->flags = kr->flags;
-}
-
-static void
-krndsource_to_rndsource_est(krndsource_t *kr, rndsource_est_t *re)
-{
- memset(re, 0, sizeof(*re));
- krndsource_to_rndsource(kr, &re->rt);
- re->dt_samples = kr->time_delta.insamples;
- re->dt_total = kr->time_delta.outbits;
- re->dv_samples = kr->value_delta.insamples;
- re->dv_total = kr->value_delta.outbits;
-}
-
-static void
-krs_setflags(krndsource_t *kr, uint32_t flags, uint32_t mask)
-{
- uint32_t oflags = kr->flags;
-
- kr->flags &= ~mask;
- kr->flags |= (flags & mask);
-
- if (oflags & RND_FLAG_HASENABLE &&
- ((oflags & RND_FLAG_NO_COLLECT) != (flags & RND_FLAG_NO_COLLECT))) {
- kr->enable(kr, !(flags & RND_FLAG_NO_COLLECT));
- }
-}
-
int
rnd_ioctl(struct file *fp, u_long cmd, void *addr)
{
- krndsource_t *kr;
- rndstat_t *rst;
- rndstat_name_t *rstnm;
- rndstat_est_t *rset;
- rndstat_est_name_t *rsetnm;
- rndctl_t *rctl;
- rnddata_t *rnddata;
- uint32_t count, start;
- int ret = 0;
- int estimate_ok = 0, estimate = 0;
-
- switch (cmd) {
- case FIONBIO:
- case FIOASYNC:
- case RNDGETENTCNT:
- break;
-
- case RNDGETPOOLSTAT:
- case RNDGETSRCNUM:
- case RNDGETSRCNAME:
- case RNDGETESTNUM:
- case RNDGETESTNAME:
- ret = kauth_authorize_device(curlwp->l_cred,
- KAUTH_DEVICE_RND_GETPRIV, NULL, NULL, NULL, NULL);
- if (ret)
- return (ret);
- break;
-
- case RNDCTL:
- ret = kauth_authorize_device(curlwp->l_cred,
- KAUTH_DEVICE_RND_SETPRIV, NULL, NULL, NULL, NULL);
- if (ret)
- return (ret);
- break;
-
- case RNDADDDATA:
- ret = kauth_authorize_device(curlwp->l_cred,
- KAUTH_DEVICE_RND_ADDDATA, NULL, NULL, NULL, NULL);
- if (ret)
- return (ret);
- estimate_ok = !kauth_authorize_device(curlwp->l_cred,
- KAUTH_DEVICE_RND_ADDDATA_ESTIMATE, NULL, NULL, NULL, NULL);
- break;
-
- default:
-#ifdef COMPAT_50
- return compat_50_rnd_ioctl(fp, cmd, addr);
-#else
- return ENOTTY;
-#endif
- }
switch (cmd) {
-
- /*
- * Handled in upper layer really, but we have to return zero
- * for it to be accepted by the upper layer.
- */
case FIONBIO:
case FIOASYNC:
- break;
-
- case RNDGETENTCNT:
- mutex_spin_enter(&rndpool_mtx);
- *(uint32_t *)addr = rndpool_get_entropy_count(&rnd_pool);
- mutex_spin_exit(&rndpool_mtx);
- break;
-
- case RNDGETPOOLSTAT:
- mutex_spin_enter(&rndpool_mtx);
- rndpool_get_stats(&rnd_pool, addr, sizeof(rndpoolstat_t));
- mutex_spin_exit(&rndpool_mtx);
- break;
-
- case RNDGETSRCNUM:
- rst = (rndstat_t *)addr;
-
- if (rst->count == 0)
- break;
-
- if (rst->count > RND_MAXSTATCOUNT)
- return (EINVAL);
-
- mutex_spin_enter(&rndpool_mtx);
- /*
- * Find the starting source by running through the
- * list of sources.
- */
- kr = LIST_FIRST(&rnd_sources);
- start = rst->start;
- while (kr != NULL && start >= 1) {
- kr = LIST_NEXT(kr, list);
- start--;
- }
-
- /*
- * Return up to as many structures as the user asked
- * for. If we run out of sources, a count of zero
- * will be returned, without an error.
- */
- for (count = 0; count < rst->count && kr != NULL; count++) {
- krndsource_to_rndsource(kr, &rst->source[count]);
- kr = LIST_NEXT(kr, list);
- }
-
- rst->count = count;
-
- mutex_spin_exit(&rndpool_mtx);
- break;
-
- case RNDGETESTNUM:
- rset = (rndstat_est_t *)addr;
-
- if (rset->count == 0)
- break;
-
- if (rset->count > RND_MAXSTATCOUNT)
- return (EINVAL);
-
- mutex_spin_enter(&rndpool_mtx);
- /*
- * Find the starting source by running through the
- * list of sources.
- */
- kr = LIST_FIRST(&rnd_sources);
- start = rset->start;
- while (kr != NULL && start > 1) {
- kr = LIST_NEXT(kr, list);
- start--;
- }
-
- /* Return up to as many structures as the user asked
- * for. If we run out of sources, a count of zero
- * will be returned, without an error.
- */
- for (count = 0; count < rset->count && kr != NULL; count++) {
- krndsource_to_rndsource_est(kr, &rset->source[count]);
- kr = LIST_NEXT(kr, list);
- }
-
- rset->count = count;
-
- mutex_spin_exit(&rndpool_mtx);
- break;
-
- case RNDGETSRCNAME:
- /*
- * Scan through the list, trying to find the name.
- */
- mutex_spin_enter(&rndpool_mtx);
- rstnm = (rndstat_name_t *)addr;
- kr = LIST_FIRST(&rnd_sources);
- while (kr != NULL) {
- if (strncmp(kr->name, rstnm->name,
- MIN(sizeof(kr->name),
- sizeof(rstnm->name))) == 0) {
- krndsource_to_rndsource(kr, &rstnm->source);
- mutex_spin_exit(&rndpool_mtx);
- return (0);
- }
- kr = LIST_NEXT(kr, list);
- }
- mutex_spin_exit(&rndpool_mtx);
-
- ret = ENOENT; /* name not found */
-
- break;
-
- case RNDGETESTNAME:
- /*
- * Scan through the list, trying to find the name.
- */
- mutex_spin_enter(&rndpool_mtx);
- rsetnm = (rndstat_est_name_t *)addr;
- kr = LIST_FIRST(&rnd_sources);
- while (kr != NULL) {
- if (strncmp(kr->name, rsetnm->name,
- MIN(sizeof(kr->name),
- sizeof(rsetnm->name))) == 0) {
- krndsource_to_rndsource_est(kr,
- &rsetnm->source);
- mutex_spin_exit(&rndpool_mtx);
- return (0);
- }
- kr = LIST_NEXT(kr, list);
- }
- mutex_spin_exit(&rndpool_mtx);
-
- ret = ENOENT; /* name not found */
-
- break;
-
- case RNDCTL:
- /*
- * Set flags to enable/disable entropy counting and/or
- * collection.
- */
- mutex_spin_enter(&rndpool_mtx);
- rctl = (rndctl_t *)addr;
- kr = LIST_FIRST(&rnd_sources);
-
- /*
- * Flags set apply to all sources of this type.
- */
- if (rctl->type != 0xff) {
- while (kr != NULL) {
- if (kr->type == rctl->type) {
- krs_setflags(kr,
- rctl->flags, rctl->mask);
- }
- kr = LIST_NEXT(kr, list);
- }
- mutex_spin_exit(&rndpool_mtx);
- return (0);
- }
-
- /*
- * scan through the list, trying to find the name
- */
- while (kr != NULL) {
- if (strncmp(kr->name, rctl->name,
- MIN(sizeof(kr->name),
- sizeof(rctl->name))) == 0) {
- krs_setflags(kr, rctl->flags, rctl->mask);
- mutex_spin_exit(&rndpool_mtx);
- return (0);
- }
- kr = LIST_NEXT(kr, list);
- }
-
- mutex_spin_exit(&rndpool_mtx);
- ret = ENOENT; /* name not found */
-
- break;
-
- case RNDADDDATA:
- /*
- * Don't seed twice if our bootloader has
- * seed loading support.
- */
- if (!boot_rsp) {
- rnddata = (rnddata_t *)addr;
-
- if (rnddata->len > sizeof(rnddata->data))
- return EINVAL;
-
- if (estimate_ok) {
- /*
- * Do not accept absurd entropy estimates, and
- * do not flood the pool with entropy such that
- * new samples are discarded henceforth.
- */
- estimate = MIN((rnddata->len * NBBY) / 2,
- MIN(rnddata->entropy,
- RND_POOLBITS / 2));
- } else {
- estimate = 0;
- }
-
- mutex_spin_enter(&rndpool_mtx);
- rndpool_add_data(&rnd_pool, rnddata->data,
- rnddata->len, estimate);
- mutex_spin_exit(&rndpool_mtx);
-
- rnd_wakeup_readers();
- }
-#ifdef RND_VERBOSE
- else {
- printf("rnd: already seeded by boot loader\n");
- }
-#endif
- break;
-
+ return 0;
default:
- return ENOTTY;
+ return rnd_system_ioctl(fp, cmd, addr);
}
-
- return (ret);
}
static int
diff --git a/sys/kern/kern_rndq.c b/sys/kern/kern_rndq.c
index a9f7780f6b5..a9fcbd60c14 100644
--- a/sys/kern/kern_rndq.c
+++ b/sys/kern/kern_rndq.c
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_rndq.c,v 1.52 2015/04/14 12:35:44 riastradh Exp $ */
+/* $NetBSD: kern_rndq.c,v 1.53 2015/04/14 12:51:30 riastradh Exp $ */
/*-
* Copyright (c) 1997-2013 The NetBSD Foundation, Inc.
@@ -32,7 +32,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_rndq.c,v 1.52 2015/04/14 12:35:44 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_rndq.c,v 1.53 2015/04/14 12:51:30 riastradh Exp $");
#include <sys/param.h>
#include <sys/atomic.h>
@@ -60,6 +60,10 @@ __KERNEL_RCSID(0, "$NetBSD: kern_rndq.c,v 1.52 2015/04/14 12:35:44 riastradh Exp
#include <dev/rnd_private.h>
+#ifdef COMPAT_50
+#include <compat/sys/rnd.h>
+#endif
+
#if defined(__HAVE_CPU_COUNTER)
#include <machine/cpu_counter.h>
#endif
@@ -1309,3 +1313,310 @@ rnd_seed(void *base, size_t len)
rnd_printf_verbose("rnd: not ready, deferring seed feed.\n");
}
}
+
+static void
+krndsource_to_rndsource(krndsource_t *kr, rndsource_t *r)
+{
+ memset(r, 0, sizeof(*r));
+ strlcpy(r->name, kr->name, sizeof(r->name));
+ r->total = kr->total;
+ r->type = kr->type;
+ r->flags = kr->flags;
+}
+
+static void
+krndsource_to_rndsource_est(krndsource_t *kr, rndsource_est_t *re)
+{
+ memset(re, 0, sizeof(*re));
+ krndsource_to_rndsource(kr, &re->rt);
+ re->dt_samples = kr->time_delta.insamples;
+ re->dt_total = kr->time_delta.outbits;
+ re->dv_samples = kr->value_delta.insamples;
+ re->dv_total = kr->value_delta.outbits;
+}
+
+static void
+krs_setflags(krndsource_t *kr, uint32_t flags, uint32_t mask)
+{
+ uint32_t oflags = kr->flags;
+
+ kr->flags &= ~mask;
+ kr->flags |= (flags & mask);
+
+ if (oflags & RND_FLAG_HASENABLE &&
+ ((oflags & RND_FLAG_NO_COLLECT) != (flags & RND_FLAG_NO_COLLECT))) {
+ kr->enable(kr, !(flags & RND_FLAG_NO_COLLECT));
+ }
+}
+
+int
+rnd_system_ioctl(struct file *fp, u_long cmd, void *addr)
+{
+ krndsource_t *kr;
+ rndstat_t *rst;
+ rndstat_name_t *rstnm;
+ rndstat_est_t *rset;
+ rndstat_est_name_t *rsetnm;
+ rndctl_t *rctl;
+ rnddata_t *rnddata;
+ uint32_t count, start;
+ int ret = 0;
+ int estimate_ok = 0, estimate = 0;
+
+ switch (cmd) {
+ case RNDGETENTCNT:
+ break;
+
+ case RNDGETPOOLSTAT:
+ case RNDGETSRCNUM:
+ case RNDGETSRCNAME:
+ case RNDGETESTNUM:
+ case RNDGETESTNAME:
+ ret = kauth_authorize_device(curlwp->l_cred,
+ KAUTH_DEVICE_RND_GETPRIV, NULL, NULL, NULL, NULL);
+ if (ret)
+ return (ret);
+ break;
+
+ case RNDCTL:
+ ret = kauth_authorize_device(curlwp->l_cred,
+ KAUTH_DEVICE_RND_SETPRIV, NULL, NULL, NULL, NULL);
+ if (ret)
+ return (ret);
+ break;
+
+ case RNDADDDATA:
+ ret = kauth_authorize_device(curlwp->l_cred,
+ KAUTH_DEVICE_RND_ADDDATA, NULL, NULL, NULL, NULL);
+ if (ret)
+ return (ret);
+ estimate_ok = !kauth_authorize_device(curlwp->l_cred,
+ KAUTH_DEVICE_RND_ADDDATA_ESTIMATE, NULL, NULL, NULL, NULL);
+ break;
+
+ default:
+#ifdef COMPAT_50
+ return compat_50_rnd_ioctl(fp, cmd, addr);
+#else
+ return ENOTTY;
+#endif
+ }
+
+ switch (cmd) {
+ case RNDGETENTCNT:
+ mutex_spin_enter(&rndpool_mtx);
+ *(uint32_t *)addr = rndpool_get_entropy_count(&rnd_pool);
+ mutex_spin_exit(&rndpool_mtx);
+ break;
+
+ case RNDGETPOOLSTAT:
+ mutex_spin_enter(&rndpool_mtx);
+ rndpool_get_stats(&rnd_pool, addr, sizeof(rndpoolstat_t));
+ mutex_spin_exit(&rndpool_mtx);
+ break;
+
+ case RNDGETSRCNUM:
+ rst = (rndstat_t *)addr;
+
+ if (rst->count == 0)
+ break;
+
+ if (rst->count > RND_MAXSTATCOUNT)
+ return (EINVAL);
+
+ mutex_spin_enter(&rndpool_mtx);
+ /*
+ * Find the starting source by running through the
+ * list of sources.
+ */
+ kr = LIST_FIRST(&rnd_sources);
+ start = rst->start;
+ while (kr != NULL && start >= 1) {
+ kr = LIST_NEXT(kr, list);
+ start--;
+ }
+
+ /*
+ * Return up to as many structures as the user asked
+ * for. If we run out of sources, a count of zero
+ * will be returned, without an error.
+ */
+ for (count = 0; count < rst->count && kr != NULL; count++) {
+ krndsource_to_rndsource(kr, &rst->source[count]);
+ kr = LIST_NEXT(kr, list);
+ }
+
+ rst->count = count;
+
+ mutex_spin_exit(&rndpool_mtx);
+ break;
+
+ case RNDGETESTNUM:
+ rset = (rndstat_est_t *)addr;
+
+ if (rset->count == 0)
+ break;
+
+ if (rset->count > RND_MAXSTATCOUNT)
+ return (EINVAL);
+
+ mutex_spin_enter(&rndpool_mtx);
+ /*
+ * Find the starting source by running through the
+ * list of sources.
+ */
+ kr = LIST_FIRST(&rnd_sources);
+ start = rset->start;
+ while (kr != NULL && start > 1) {
+ kr = LIST_NEXT(kr, list);
+ start--;
+ }
+
+ /* Return up to as many structures as the user asked
+ * for. If we run out of sources, a count of zero
+ * will be returned, without an error.
+ */
+ for (count = 0; count < rset->count && kr != NULL; count++) {
+ krndsource_to_rndsource_est(kr, &rset->source[count]);
+ kr = LIST_NEXT(kr, list);
+ }
+
+ rset->count = count;
+
+ mutex_spin_exit(&rndpool_mtx);
+ break;
+
+ case RNDGETSRCNAME:
+ /*
+ * Scan through the list, trying to find the name.
+ */
+ mutex_spin_enter(&rndpool_mtx);
+ rstnm = (rndstat_name_t *)addr;
+ kr = LIST_FIRST(&rnd_sources);
+ while (kr != NULL) {
+ if (strncmp(kr->name, rstnm->name,
+ MIN(sizeof(kr->name),
+ sizeof(rstnm->name))) == 0) {
+ krndsource_to_rndsource(kr, &rstnm->source);
+ mutex_spin_exit(&rndpool_mtx);
+ return (0);
+ }
+ kr = LIST_NEXT(kr, list);
+ }
+ mutex_spin_exit(&rndpool_mtx);
+
+ ret = ENOENT; /* name not found */
+
+ break;
+
+ case RNDGETESTNAME:
+ /*
+ * Scan through the list, trying to find the name.
+ */
+ mutex_spin_enter(&rndpool_mtx);
+ rsetnm = (rndstat_est_name_t *)addr;
+ kr = LIST_FIRST(&rnd_sources);
+ while (kr != NULL) {
+ if (strncmp(kr->name, rsetnm->name,
+ MIN(sizeof(kr->name),
+ sizeof(rsetnm->name))) == 0) {
+ krndsource_to_rndsource_est(kr,
+ &rsetnm->source);
+ mutex_spin_exit(&rndpool_mtx);
+ return (0);
+ }
+ kr = LIST_NEXT(kr, list);
+ }
+ mutex_spin_exit(&rndpool_mtx);
+
+ ret = ENOENT; /* name not found */
+
+ break;
+
+ case RNDCTL:
+ /*
+ * Set flags to enable/disable entropy counting and/or
+ * collection.
+ */
+ mutex_spin_enter(&rndpool_mtx);
+ rctl = (rndctl_t *)addr;
+ kr = LIST_FIRST(&rnd_sources);
+
+ /*
+ * Flags set apply to all sources of this type.
+ */
+ if (rctl->type != 0xff) {
+ while (kr != NULL) {
+ if (kr->type == rctl->type) {
+ krs_setflags(kr,
+ rctl->flags, rctl->mask);
+ }
+ kr = LIST_NEXT(kr, list);
+ }
+ mutex_spin_exit(&rndpool_mtx);
+ return (0);
+ }
+
+ /*
+ * scan through the list, trying to find the name
+ */
+ while (kr != NULL) {
+ if (strncmp(kr->name, rctl->name,
+ MIN(sizeof(kr->name),
+ sizeof(rctl->name))) == 0) {
+ krs_setflags(kr, rctl->flags, rctl->mask);
+ mutex_spin_exit(&rndpool_mtx);
+ return (0);
+ }
+ kr = LIST_NEXT(kr, list);
+ }
+
+ mutex_spin_exit(&rndpool_mtx);
+ ret = ENOENT; /* name not found */
+
+ break;
+
+ case RNDADDDATA:
+ /*
+ * Don't seed twice if our bootloader has
+ * seed loading support.
+ */
+ if (!boot_rsp) {
+ rnddata = (rnddata_t *)addr;
+
+ if (rnddata->len > sizeof(rnddata->data))
+ return EINVAL;
+
+ if (estimate_ok) {
+ /*
+ * Do not accept absurd entropy estimates, and
+ * do not flood the pool with entropy such that
+ * new samples are discarded henceforth.
+ */
+ estimate = MIN((rnddata->len * NBBY) / 2,
+ MIN(rnddata->entropy,
+ RND_POOLBITS / 2));
+ } else {
+ estimate = 0;
+ }
+
+ mutex_spin_enter(&rndpool_mtx);
+ rndpool_add_data(&rnd_pool, rnddata->data,
+ rnddata->len, estimate);
+ mutex_spin_exit(&rndpool_mtx);
+
+ rnd_wakeup_readers();
+ }
+#ifdef RND_VERBOSE
+ else {
+ printf("rnd: already seeded by boot loader\n");
+ }
+#endif
+ break;
+
+ default:
+ return ENOTTY;
+ }
+
+ return (ret);
+}
diff --git a/sys/sys/rnd.h b/sys/sys/rnd.h
index f30988eb1eb..98df0b6f990 100644
--- a/sys/sys/rnd.h
+++ b/sys/sys/rnd.h
@@ -1,4 +1,4 @@
-/* $NetBSD: rnd.h,v 1.48 2015/04/13 22:52:52 riastradh Exp $ */
+/* $NetBSD: rnd.h,v 1.49 2015/04/14 12:51:30 riastradh Exp $ */
/*-
* Copyright (c) 1997 The NetBSD Foundation, Inc.
@@ -35,12 +35,17 @@
#ifdef _KERNEL
+#include <sys/types.h>
+
+struct file;
+
#define RND_DEV_RANDOM 0 /* minor for blocking until unpredictable */
#define RND_DEV_URANDOM 1 /* minor for randomly generating data */
void rnd_init(void);
void rnd_init_softint(void);
void rnd_seed(void *, size_t);
+int rnd_system_ioctl(struct file *, u_long, void *);
extern int rnd_initial_entropy;