diff options
Diffstat (limited to 'sys')
| -rw-r--r-- | sys/dev/rndpseudo.c | 316 | ||||
| -rw-r--r-- | sys/kern/kern_rndq.c | 315 | ||||
| -rw-r--r-- | sys/sys/rnd.h | 7 |
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; |
