Module Name: src
Committed By: tls
Date: Wed Nov 23 10:47:50 UTC 2011
Modified Files:
src/distrib/sets/lists/etc: mi
src/etc/defaults: rc.conf
src/etc/rc.d: Makefile
src/sbin/rndctl: rndctl.8 rndctl.c
src/sys/dev: rnd.c
src/sys/secmodel/securelevel: secmodel_securelevel.c
src/sys/secmodel/suser: secmodel_suser.c
src/sys/sys: kauth.h rnd.h
Added Files:
src/etc/rc.d: random_seed
Log Message:
Load entropy at system boot (only works at securelevel < 1); save
at system shutdown. Disable with random_seed=NO in rc.conf if desired.
Goes to some trouble to never load or save to network filesystems.
Entropy should really be loaded by the boot loader but I am still
sorting out how to pass it to the kernel.
To generate a diff of this commit:
cvs rdiff -u -r1.225 -r1.226 src/distrib/sets/lists/etc/mi
cvs rdiff -u -r1.116 -r1.117 src/etc/defaults/rc.conf
cvs rdiff -u -r1.85 -r1.86 src/etc/rc.d/Makefile
cvs rdiff -u -r0 -r1.1 src/etc/rc.d/random_seed
cvs rdiff -u -r1.18 -r1.19 src/sbin/rndctl/rndctl.8
cvs rdiff -u -r1.20 -r1.21 src/sbin/rndctl/rndctl.c
cvs rdiff -u -r1.85 -r1.86 src/sys/dev/rnd.c
cvs rdiff -u -r1.20 -r1.21 \
src/sys/secmodel/securelevel/secmodel_securelevel.c
cvs rdiff -u -r1.34 -r1.35 src/sys/secmodel/suser/secmodel_suser.c
cvs rdiff -u -r1.64 -r1.65 src/sys/sys/kauth.h
cvs rdiff -u -r1.22 -r1.23 src/sys/sys/rnd.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/distrib/sets/lists/etc/mi
diff -u src/distrib/sets/lists/etc/mi:1.225 src/distrib/sets/lists/etc/mi:1.226
--- src/distrib/sets/lists/etc/mi:1.225 Tue Sep 6 21:32:30 2011
+++ src/distrib/sets/lists/etc/mi Wed Nov 23 10:47:49 2011
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.225 2011/09/06 21:32:30 riz Exp $
+# $NetBSD: mi,v 1.226 2011/11/23 10:47:49 tls Exp $
#
# Note: end-user configuration files that are moved to another location
# should not be marked "obsolete"; they should just be removed from
@@ -254,6 +254,7 @@
./etc/rc.d/racoon etc-net-rc
./etc/rc.d/raidframe etc-sys-rc
./etc/rc.d/raidframeparity etc-sys-rc
+./etc/rc.d/random_seed etc-sys-rc
./etc/rc.d/rarpd etc-bootserver-rc
./etc/rc.d/rbootd etc-bootserver-rc
./etc/rc.d/rndctl etc-sys-rc
Index: src/etc/defaults/rc.conf
diff -u src/etc/defaults/rc.conf:1.116 src/etc/defaults/rc.conf:1.117
--- src/etc/defaults/rc.conf:1.116 Mon Nov 21 20:56:21 2011
+++ src/etc/defaults/rc.conf Wed Nov 23 10:47:48 2011
@@ -1,4 +1,4 @@
-# $NetBSD: rc.conf,v 1.116 2011/11/21 20:56:21 darcy Exp $
+# $NetBSD: rc.conf,v 1.117 2011/11/23 10:47:48 tls Exp $
#
# /etc/defaults/rc.conf --
# default configuration of /etc/rc.conf
@@ -362,3 +362,6 @@ veriexec_strict=0
veriexec_verbose=0
veriexec_flags="-k"
+# Entropy load/save to/from /dev/random at startup/shutdown
+#
+random_seed=YES
Index: src/etc/rc.d/Makefile
diff -u src/etc/rc.d/Makefile:1.85 src/etc/rc.d/Makefile:1.86
--- src/etc/rc.d/Makefile:1.85 Tue Sep 6 21:32:29 2011
+++ src/etc/rc.d/Makefile Wed Nov 23 10:47:48 2011
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.85 2011/09/06 21:32:29 riz Exp $
+# $NetBSD: Makefile,v 1.86 2011/11/23 10:47:48 tls Exp $
.include <bsd.own.mk>
@@ -31,8 +31,9 @@ CONFIGFILES=\
named ndbootd network newsyslog nfsd nfslocking npf ntpd ntpdate \
perusertmp pf pf_boot pflogd postfix powerd ppp pwcheck \
quota \
- racoon rpcbind raidframe raidframeparity rarpd rbootd rndctl \
- root route6d routed rtadvd rtclocaltime rtsold rwho \
+ racoon rpcbind raidframe raidframeparity random_seed rarpd \
+ rbootd rndctl root route6d routed rtadvd rtclocaltime \
+ rtsold rwho \
savecore screenblank securelevel sshd \
staticroute swap1 swap2 sysctl sysdb syslogd \
timed tpctl ttys \
Index: src/sbin/rndctl/rndctl.8
diff -u src/sbin/rndctl/rndctl.8:1.18 src/sbin/rndctl/rndctl.8:1.19
--- src/sbin/rndctl/rndctl.8:1.18 Sat Oct 1 02:55:00 2011
+++ src/sbin/rndctl/rndctl.8 Wed Nov 23 10:47:49 2011
@@ -1,4 +1,4 @@
-.\" $NetBSD: rndctl.8,v 1.18 2011/10/01 02:55:00 pgoyette Exp $
+.\" $NetBSD: rndctl.8,v 1.19 2011/11/23 10:47:49 tls Exp $
.\"
.\" Copyright (c) 1997 Michael Graff
.\" All rights reserved.
@@ -39,6 +39,10 @@
.Nm
.Fl ls
.Op Fl d Ar devname | Fl t Ar devtype
+.Nm
+.Fl L Ar save-file
+.Nm
+.Fl S Ar save-file
.Sh DESCRIPTION
The
.Nm
@@ -104,6 +108,17 @@ Terminal, mouse, or other user input dev
.It Ic rng
Random number generators.
.El
+.It Fl L
+Load saved entropy from file
+.Ar save-file ,
+which will be overwritten and deleted before the entropy is loaded into
+the kernel.
+.It Fl S
+Save entropy pool to file
+.Ar save-file .
+The file format is specific to
+.Nm
+and includes an estimate of the amount of saved entropy and a checksum.
.El
.Sh FILES
.Bl -tag -width /dev/urandomx -compact
Index: src/sbin/rndctl/rndctl.c
diff -u src/sbin/rndctl/rndctl.c:1.20 src/sbin/rndctl/rndctl.c:1.21
--- src/sbin/rndctl/rndctl.c:1.20 Sat Aug 27 18:48:59 2011
+++ src/sbin/rndctl/rndctl.c Wed Nov 23 10:47:49 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: rndctl.c,v 1.20 2011/08/27 18:48:59 joerg Exp $ */
+/* $NetBSD: rndctl.c,v 1.21 2011/11/23 10:47:49 tls Exp $ */
/*-
* Copyright (c) 1997 Michael Graff.
@@ -29,14 +29,17 @@
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <sha1.h>
#ifndef lint
-__RCSID("$NetBSD: rndctl.c,v 1.20 2011/08/27 18:48:59 joerg Exp $");
+__RCSID("$NetBSD: rndctl.c,v 1.21 2011/11/23 10:47:49 tls Exp $");
#endif
#include <sys/types.h>
#include <sys/ioctl.h>
+#include <sys/param.h>
#include <sys/rnd.h>
#include <stdio.h>
@@ -48,6 +51,12 @@ __RCSID("$NetBSD: rndctl.c,v 1.20 2011/0
#include <string.h>
typedef struct {
+ uint32_t entropy;
+ uint8_t data[RND_POOLWORDS * sizeof(uint32_t)];
+ uint8_t digest[SHA1_DIGEST_LENGTH];
+} rndsave_t;
+
+typedef struct {
const char *a_name;
u_int32_t a_type;
} arg_t;
@@ -78,6 +87,7 @@ usage(void)
getprogname());
fprintf(stderr, " %s -ls [-d devname | -t devtype]\n",
getprogname());
+ fprintf(stderr, " %s -[L|S] save-file\n", getprogname());
exit(1);
}
@@ -116,6 +126,114 @@ find_name(u_int32_t type)
}
static void
+do_save(const char *const filename)
+{
+ int est1, est2;
+ rndpoolstat_t rp;
+ rndsave_t rs;
+ SHA1_CTX s;
+
+ int fd;
+
+ fd = open("/dev/urandom", O_RDONLY, 0644);
+ if (fd < 0) {
+ err(1, "device open");
+ }
+
+ if (ioctl(fd, RNDGETPOOLSTAT, &rp) < 0) {
+ err(1, "ioctl(RNDGETPOOLSTAT)");
+ }
+
+ est1 = rp.curentropy;
+
+ if (read(fd, rs.data, sizeof(rs.data)) != sizeof(rs.data)) {
+ err(1, "entropy read");
+ }
+
+ if (ioctl(fd, RNDGETPOOLSTAT, &rp) < 0) {
+ err(1, "ioctl(RNDGETPOOLSTAT)");
+ }
+
+ est2 = rp.curentropy;
+
+ if (est1 - est2 < 0) {
+ rs.entropy = 0;
+ } else {
+ rs.entropy = est1 - est2;
+ }
+
+ SHA1Init(&s);
+ SHA1Update(&s, (uint8_t *)&rs.entropy, sizeof(rs.entropy));
+ SHA1Update(&s, rs.data, sizeof(rs.data));
+ SHA1Final(rs.digest, &s);
+
+ close(fd);
+ unlink(filename);
+ fd = open(filename, O_CREAT|O_EXCL|O_WRONLY, 0600);
+ if (fd < 0) {
+ err(1, "output open");
+ }
+
+ if (write(fd, &rs, sizeof(rs)) != sizeof(rs)) {
+ unlink(filename);
+ fsync_range(fd, FDATASYNC|FDISKSYNC, (off_t)0, (off_t)0);
+ err(1, "write");
+ }
+ fsync_range(fd, FDATASYNC|FDISKSYNC, (off_t)0, (off_t)0);
+ close(fd);
+}
+
+static void
+do_load(const char *const filename)
+{
+ int fd;
+ rndsave_t rs;
+ rnddata_t rd;
+ SHA1_CTX s;
+ uint8_t digest[SHA1_DIGEST_LENGTH];
+
+ fd = open(filename, O_RDWR, 0600);
+ if (fd < 0) {
+ err(1, "input open");
+ }
+
+ unlink(filename);
+
+ if (read(fd, &rs, sizeof(rs)) != sizeof(rs)) {
+ err(1, "read");
+ }
+
+ if (write(fd, &rs, sizeof(rs) != sizeof(rs))) {
+ err(1, "overwrite");
+ }
+ fsync_range(fd, FDATASYNC|FDISKSYNC, (off_t)0, (off_t)0);
+ close(fd);
+
+ SHA1Init(&s);
+ SHA1Update(&s, (uint8_t *)&rs.entropy, sizeof(rs.entropy));
+ SHA1Update(&s, rs.data, sizeof(rs.data));
+ SHA1Final(digest, &s);
+
+ if (memcmp(digest, rs.digest, sizeof(digest))) {
+ errx(1, "bad digest");
+ }
+
+ rd.len = MIN(sizeof(rd.data), sizeof(rs.data));
+ rd.entropy = rs.entropy;
+ memcpy(rd.data, rs.data, MIN(sizeof(rd.data), sizeof(rs.data)));
+
+ fd = open("/dev/urandom", O_RDWR, 0644);
+ if (fd < 0) {
+ err(1, "device open");
+ }
+
+ if (ioctl(fd, RNDADDDATA, &rd) < 0) {
+ err(1, "ioctl");
+ }
+ close(fd);
+}
+
+static void
do_ioctl(rndctl_t *rctl)
{
int fd;
@@ -247,6 +365,7 @@ main(int argc, char **argv)
int ch, cmd, lflag, mflag, sflag;
u_int32_t type;
char name[16];
+ const char *filename = NULL;
rctl.mask = 0;
rctl.flags = 0;
@@ -257,7 +376,7 @@ main(int argc, char **argv)
sflag = 0;
type = 0xff;
- while ((ch = getopt(argc, argv, "CEcelt:d:s")) != -1) {
+ while ((ch = getopt(argc, argv, "CES:L:celt:d:s")) != -1) {
switch (ch) {
case 'C':
rctl.flags |= RND_FLAG_NO_COLLECT;
@@ -269,6 +388,18 @@ main(int argc, char **argv)
rctl.mask |= RND_FLAG_NO_ESTIMATE;
mflag++;
break;
+ case 'L':
+ if (cmd != 0)
+ usage();
+ cmd = 'L';
+ filename = optarg;
+ break;
+ case 'S':
+ if (cmd != 0)
+ usage();
+ cmd = 'S';
+ filename = optarg;
+ break;
case 'c':
rctl.flags &= ~RND_FLAG_NO_COLLECT;
rctl.mask |= RND_FLAG_NO_COLLECT;
@@ -315,6 +446,22 @@ main(int argc, char **argv)
usage();
/*
+ * Save.
+ */
+ if (cmd == 'S') {
+ do_save(filename);
+ exit(0);
+ }
+
+ /*
+ * Load.
+ */
+ if (cmd == 'L') {
+ do_load(filename);
+ exit(0);
+ }
+
+ /*
* Cannot list and modify at the same time.
*/
if ((lflag != 0 || sflag != 0) && mflag != 0)
Index: src/sys/dev/rnd.c
diff -u src/sys/dev/rnd.c:1.85 src/sys/dev/rnd.c:1.86
--- src/sys/dev/rnd.c:1.85 Sun Nov 20 00:45:15 2011
+++ src/sys/dev/rnd.c Wed Nov 23 10:47:48 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: rnd.c,v 1.85 2011/11/20 00:45:15 tls Exp $ */
+/* $NetBSD: rnd.c,v 1.86 2011/11/23 10:47:48 tls Exp $ */
/*-
* Copyright (c) 1997-2011 The NetBSD Foundation, Inc.
@@ -32,7 +32,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rnd.c,v 1.85 2011/11/20 00:45:15 tls Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rnd.c,v 1.86 2011/11/23 10:47:48 tls Exp $");
#include <sys/param.h>
#include <sys/ioctl.h>
@@ -509,7 +509,15 @@ int
rndwrite(dev_t dev, struct uio *uio, int ioflag)
{
u_int8_t *bf;
- int n, ret;
+ int n, ret = 0, estimate_ok = 0, estimate = 0, added = 0;
+
+ 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);
DPRINTF(RND_DEBUG_WRITE,
("Random: Write of %zu requested\n", uio->uio_resid));
@@ -519,19 +527,43 @@ rndwrite(dev_t dev, struct uio *uio, int
ret = 0;
bf = kmem_alloc(RND_TEMP_BUFFER_SIZE, KM_SLEEP);
while (uio->uio_resid > 0) {
+ /*
+ * Don't flood the pool.
+ */
+ if (added > RND_POOLWORDS * sizeof(int)) {
+ printf("rnd: added %d already, adding no more.\n",
+ added);
+ break;
+ }
n = min(RND_TEMP_BUFFER_SIZE, uio->uio_resid);
ret = uiomove((void *)bf, n, uio);
if (ret != 0)
break;
+ if (estimate_ok) {
+ /*
+ * Don't cause samples to be discarded by taking
+ * the pool's entropy estimate to the max.
+ */
+ if (added > RND_POOLWORDS / 2)
+ estimate = 0;
+ else
+ estimate = n * NBBY / 2;
+ printf("rnd: adding on write, %d bytes, estimate %d\n",
+ n, estimate);
+ } else {
+ printf("rnd: kauth says no entropy.\n");
+ }
+
/*
* Mix in the bytes.
*/
mutex_spin_enter(&rndpool_mtx);
- rndpool_add_data(&rnd_pool, bf, n, 0);
+ rndpool_add_data(&rnd_pool, bf, n, estimate);
mutex_spin_exit(&rndpool_mtx);
+ added += n;
DPRINTF(RND_DEBUG_WRITE, ("Random: Copied in %d bytes\n", n));
}
kmem_free(bf, RND_TEMP_BUFFER_SIZE);
@@ -558,9 +590,8 @@ rndioctl(dev_t dev, u_long cmd, void *ad
rndctl_t *rctl;
rnddata_t *rnddata;
u_int32_t count, start;
- int ret;
-
- ret = 0;
+ int ret = 0;
+ int estimate_ok = 0, estimate = 0;
switch (cmd) {
case FIONBIO:
@@ -589,6 +620,8 @@ rndioctl(dev_t dev, u_long cmd, void *ad
KAUTH_DEVICE_RND_ADDDATA, NULL, NULL, NULL, NULL);
if (ret)
return (ret);
+ estimate_ok = !kauth_authorize_device(l->l_cred,
+ KAUTH_DEVICE_RND_ADDDATA_ESTIMATE, NULL, NULL, NULL, NULL);
break;
default:
@@ -720,9 +753,23 @@ rndioctl(dev_t dev, u_long cmd, void *ad
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_POOLWORDS * sizeof(int) *
+ NBBY / 2));
+ } else {
+ estimate = 0;
+ }
+
mutex_spin_enter(&rndpool_mtx);
rndpool_add_data(&rnd_pool, rnddata->data, rnddata->len,
- rnddata->entropy);
+ estimate);
mutex_spin_exit(&rndpool_mtx);
rnd_wakeup_readers();
Index: src/sys/secmodel/securelevel/secmodel_securelevel.c
diff -u src/sys/secmodel/securelevel/secmodel_securelevel.c:1.20 src/sys/secmodel/securelevel/secmodel_securelevel.c:1.21
--- src/sys/secmodel/securelevel/secmodel_securelevel.c:1.20 Wed Oct 7 01:06:57 2009
+++ src/sys/secmodel/securelevel/secmodel_securelevel.c Wed Nov 23 10:47:48 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: secmodel_securelevel.c,v 1.20 2009/10/07 01:06:57 elad Exp $ */
+/* $NetBSD: secmodel_securelevel.c,v 1.21 2011/11/23 10:47:48 tls Exp $ */
/*-
* Copyright (c) 2006 Elad Efrat <[email protected]>
* All rights reserved.
@@ -35,7 +35,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: secmodel_securelevel.c,v 1.20 2009/10/07 01:06:57 elad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: secmodel_securelevel.c,v 1.21 2011/11/23 10:47:48 tls Exp $");
#ifdef _KERNEL_OPT
#include "opt_insecure.h"
@@ -553,6 +553,11 @@ secmodel_securelevel_device_cb(kauth_cre
result = KAUTH_RESULT_DENY;
break;
+ case KAUTH_DEVICE_RND_ADDDATA_ESTIMATE:
+ if (securelevel > 0)
+ result = KAUTH_RESULT_DENY;
+ break;
+
default:
break;
}
Index: src/sys/secmodel/suser/secmodel_suser.c
diff -u src/sys/secmodel/suser/secmodel_suser.c:1.34 src/sys/secmodel/suser/secmodel_suser.c:1.35
--- src/sys/secmodel/suser/secmodel_suser.c:1.34 Tue Dec 29 04:25:30 2009
+++ src/sys/secmodel/suser/secmodel_suser.c Wed Nov 23 10:47:49 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: secmodel_suser.c,v 1.34 2009/12/29 04:25:30 elad Exp $ */
+/* $NetBSD: secmodel_suser.c,v 1.35 2011/11/23 10:47:49 tls Exp $ */
/*-
* Copyright (c) 2006 Elad Efrat <[email protected]>
* All rights reserved.
@@ -38,7 +38,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: secmodel_suser.c,v 1.34 2009/12/29 04:25:30 elad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: secmodel_suser.c,v 1.35 2011/11/23 10:47:49 tls Exp $");
#include <sys/types.h>
#include <sys/param.h>
@@ -838,6 +838,7 @@ secmodel_suser_device_cb(kauth_cred_t cr
case KAUTH_DEVICE_TTY_PRIVSET:
case KAUTH_DEVICE_TTY_STI:
case KAUTH_DEVICE_RND_ADDDATA:
+ case KAUTH_DEVICE_RND_ADDDATA_ESTIMATE:
case KAUTH_DEVICE_RND_GETPRIV:
case KAUTH_DEVICE_RND_SETPRIV:
if (isroot)
Index: src/sys/sys/kauth.h
diff -u src/sys/sys/kauth.h:1.64 src/sys/sys/kauth.h:1.65
--- src/sys/sys/kauth.h:1.64 Thu Dec 24 19:02:07 2009
+++ src/sys/sys/kauth.h Wed Nov 23 10:47:49 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: kauth.h,v 1.64 2009/12/24 19:02:07 elad Exp $ */
+/* $NetBSD: kauth.h,v 1.65 2011/11/23 10:47:49 tls Exp $ */
/*-
* Copyright (c) 2005, 2006 Elad Efrat <[email protected]>
@@ -255,6 +255,7 @@ enum {
KAUTH_DEVICE_RAWIO_PASSTHRU,
KAUTH_DEVICE_BLUETOOTH_SETPRIV,
KAUTH_DEVICE_RND_ADDDATA,
+ KAUTH_DEVICE_RND_ADDDATA_ESTIMATE,
KAUTH_DEVICE_RND_GETPRIV,
KAUTH_DEVICE_RND_SETPRIV,
KAUTH_DEVICE_BLUETOOTH_BCSP,
Index: src/sys/sys/rnd.h
diff -u src/sys/sys/rnd.h:1.22 src/sys/sys/rnd.h:1.23
--- src/sys/sys/rnd.h:1.22 Sat Nov 19 22:51:31 2011
+++ src/sys/sys/rnd.h Wed Nov 23 10:47:49 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: rnd.h,v 1.22 2011/11/19 22:51:31 tls Exp $ */
+/* $NetBSD: rnd.h,v 1.23 2011/11/23 10:47:49 tls Exp $ */
/*-
* Copyright (c) 1997 The NetBSD Foundation, Inc.
@@ -209,7 +209,7 @@ typedef struct {
typedef struct {
uint32_t len;
uint32_t entropy;
- u_char data[RND_POOLWORDS * 4];
+ u_char data[RND_POOLWORDS * sizeof(uint32_t)];
} rnddata_t;
#define RNDGETENTCNT _IOR('R', 101, uint32_t) /* get entropy count */
Added files:
Index: src/etc/rc.d/random_seed
diff -u /dev/null src/etc/rc.d/random_seed:1.1
--- /dev/null Wed Nov 23 10:47:50 2011
+++ src/etc/rc.d/random_seed Wed Nov 23 10:47:48 2011
@@ -0,0 +1,91 @@
+#!/bin/sh
+#
+# $NetBSD: random_seed,v 1.1 2011/11/23 10:47:48 tls Exp $
+#
+
+# PROVIDE: random_seed
+# REQUIRE: mountcritlocal
+# BEFORE: securelevel
+# KEYWORD: shutdown
+
+$_rc_subr_loaded . /etc/rc.subr
+
+name="random_seed"
+rcvar=$name
+start_cmd="random_load"
+stop_cmd="random_save"
+
+random_file=${random_file:-/var/db/entropy-file}
+
+fs_safe()
+{
+ #
+ # Enforce that the file's on a local filesystem.
+ # Include only the types we can actually write.
+ #
+ fstype=$(df -G $1 | awk '$2 == "fstype" {print $1}')
+ case $fstype in
+ ffs)
+ return 0
+ ;;
+ lfs)
+ return 0
+ ;;
+ ext2fs)
+ return 0;
+ ;;
+ msdosfs)
+ return 0;
+ ;;
+ v7fs)
+ return 0;
+ ;;
+ esac
+ return 1
+}
+
+random_load()
+{
+ if [ -f $random_file ]; then
+
+ if ! fs_safe $(dirname ${random_file}); then
+ return 1
+ fi
+
+ eval $(stat -s ${random_file})
+
+ # The file must be owned by root,
+ if [ "$st_uid" != "0" ]; then
+ return 1
+ fi
+ # and root read/write only.
+ if [ "$(echo $st_mode | tail -c4)" != "600" ]; then
+ return 1
+ fi
+
+ if rndctl -L ${random_file}; then
+ echo "Loaded entropy from disk."
+ fi
+
+ fi
+}
+
+random_save()
+{
+ oum=$(umask)
+ umask 077
+
+ rm -Pf ${random_file}
+
+ if ! fs_safe $(dirname ${random_file}); then
+ return 1
+ fi
+
+ if rndctl -S ${random_file}; then
+ echo "Saved entropy to disk."
+ fi
+}
+
+
+load_rc_config $name
+run_rc_command "$1"