Preserve random seed across reboots
At first I tried to just use systemd's systemd-random-seed, but that one
does not actually use an appropriate ioctl for persuading kernel that
entropy is there. There's a patch [1] for this, but its fate is far from
certain, and even with it, I am not completely sure that I got
everything working correctly (some boots were quick, others waited for
systemd-resolved in the same manner as before this patch).
In the end, just seeding stuff from the initrd [2] is much easier. A
downside is that the systemd unit systemd-random-seed.service will add
the contents of that file once again -- but that doesn't matter much
because we do not patch it, and therefore it does not increase kernel's
idea about available entropy.
Changes from that upstream rndaddentropy:
- larger buffer
- more conservative entropy contribution
[1] https://github.com/systemd/systemd/pull/10621 .
[2] https://github.com/rfinnie/twuewand/blob/master/rndaddentropy/rndaddentropy.c
Change-Id: Ibe3c926c241d75fb7d7c40f3df2a96813931971b
diff --git a/board/czechlight/common/patches/systemd/random-seed.patch b/board/czechlight/common/patches/systemd/random-seed.patch
new file mode 100644
index 0000000..5eed6f5
--- /dev/null
+++ b/board/czechlight/common/patches/systemd/random-seed.patch
@@ -0,0 +1,26 @@
+diff --git a/meson.build b/meson.build
+index b338886c38..a968af87ee 100644
+--- a/meson.build
++++ b/meson.build
+@@ -146,7 +146,7 @@ bootlibdir = join_paths(prefixdir, 'lib/systemd/boot/efi')
+ testsdir = join_paths(prefixdir, 'lib/systemd/tests')
+ systemdstatedir = join_paths(localstatedir, 'lib/systemd')
+ catalogstatedir = join_paths(systemdstatedir, 'catalog')
+-randomseeddir = join_paths(localstatedir, 'lib/systemd')
++randomseeddir = '/cfg/random-seed'
+ profiledir = join_paths(rootlibexecdir, 'portable', 'profile')
+
+ docdir = get_option('docdir')
+diff --git a/src/random-seed/random-seed.c b/src/random-seed/random-seed.c
+index 0c5f329756..f30f32fb61 100644
+--- a/src/random-seed/random-seed.c
++++ b/src/random-seed/random-seed.c
+@@ -17,7 +17,7 @@
+ #include "string-util.h"
+ #include "util.h"
+
+-#define POOL_SIZE_MIN 512
++#define POOL_SIZE_MIN 4096
+ #define POOL_SIZE_MAX (10*1024*1024)
+
+ static int run(int argc, char *argv[]) {
diff --git a/configs/czechlight_clearfog_defconfig b/configs/czechlight_clearfog_defconfig
index 0e547fa..bf75605 100644
--- a/configs/czechlight_clearfog_defconfig
+++ b/configs/czechlight_clearfog_defconfig
@@ -6,6 +6,7 @@
BR2_ENABLE_DEBUG=y
BR2_STRIP_EXCLUDE_FILES="cla-* netopeer2* sysrepo* libsysrepo* libSysrepo* libnetconf2* libyang* netconf-cli"
BR2_STRIP_EXCLUDE_DIRS="/usr/lib/libyang /usr/lib/sysrepo"
+BR2_GLOBAL_PATCH_DIR="$(BR2_EXTERNAL_CZECHLIGHT_PATH)/board/czechlight/common/patches"
BR2_REPRODUCIBLE=y
BR2_SSP_STRONG=y
BR2_TOOLCHAIN_EXTERNAL=y
@@ -52,6 +53,7 @@
BR2_PACKAGE_RAUC=y
BR2_PACKAGE_RAUC_NETWORK=y
# BR2_PACKAGE_SYSTEMD_HWDB is not set
+BR2_PACKAGE_SYSTEMD_RANDOMSEED=y
# BR2_PACKAGE_SYSTEMD_VCONSOLE is not set
BR2_PACKAGE_VIM=y
# BR2_PACKAGE_VIM_RUNTIME is not set
diff --git a/package/czechlight-cfg-fs/czechlight-cfg-fs.mk b/package/czechlight-cfg-fs/czechlight-cfg-fs.mk
index 98ca80c..67f2e55 100644
--- a/package/czechlight-cfg-fs/czechlight-cfg-fs.mk
+++ b/package/czechlight-cfg-fs/czechlight-cfg-fs.mk
@@ -12,10 +12,15 @@
$(error CZECHLIGHT_CFG_FS_SIZE cannot be empty)
endif
+define CZECHLIGHT_CFG_FS_BUILD_CMDS
+ $(TARGET_CC) $(BR2_EXTERNAL_CZECHLIGHT_PATH)/package/czechlight-cfg-fs/czechlight-random-seed.c -o czechlight-random-seed
+endef
+
define CZECHLIGHT_CFG_FS_INSTALL_TARGET_CMDS
$(INSTALL) -D -m 0755 \
$(BR2_EXTERNAL_CZECHLIGHT_PATH)/package/czechlight-cfg-fs/init-czechlight.sh \
$(TARGET_DIR)/sbin/init-czechlight.sh
+ $(INSTALL) -D -m 0755 czechlight-random-seed $(TARGET_DIR)/sbin/czechlight-random-seed
mkdir -p $(TARGET_DIR)/cfg
$(ifeq ($(CZECHLIGHT_CFG_FS_PERSIST_SYSREPO),y))
mkdir -p $(TARGET_DIR)/usr/lib/systemd/system/multi-user.target.wants/
diff --git a/package/czechlight-cfg-fs/czechlight-random-seed.c b/package/czechlight-cfg-fs/czechlight-random-seed.c
new file mode 100644
index 0000000..ac5c94a
--- /dev/null
+++ b/package/czechlight-cfg-fs/czechlight-random-seed.c
@@ -0,0 +1,70 @@
+/* rndaddentropy, an RNDADDENTROPY ioctl wrapper
+ * Copyright (C) 2012 Ryan Finnie <ryan@finnie.org>
+ *
+ * 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, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/fcntl.h>
+#include <sys/ioctl.h>
+#include <linux/random.h>
+
+int main(int argc, char *argv[]) {
+ struct {
+ int entropy_count;
+ int buf_size;
+ char buf[8192];
+ } entropy;
+
+ int i;
+ for(i=1; i < argc; i++) {
+ if(strcmp(argv[i], "--help") == 0) {
+ fprintf(stderr, "rndaddentropy, an RNDADDENTROPY ioctl wrapper\n");
+ fprintf(stderr, "Copyright (C) 2012 Ryan Finnie <ryan@finnie.org>\n");
+ fprintf(stderr, "\n");
+ fprintf(stderr, "Usage: $ENTROPY_GENERATOR | rndaddentropy\n");
+ fprintf(stderr, "\n");
+ fprintf(stderr, "WARNING! This program is dangerous, and relies on your entropy\n");
+ fprintf(stderr, "generator producing adequate output. Inadequate entropy generation\n");
+ fprintf(stderr, "fed to the primary pool is a security risk to the system.\n");
+ return(1);
+ }
+ }
+
+ int randfd;
+ if((randfd = open("/dev/random", O_WRONLY)) < 0) {
+ perror("/dev/random");
+ return(1);
+ }
+
+ int count;
+ while((count = fread(entropy.buf, 1, sizeof(entropy.buf), stdin)) > 0) {
+ // Jan Kundrat: be more conservative -- one bit of entropy per 16 bytes of randomness
+ entropy.entropy_count = count / 16;
+ if (entropy.entropy_count < 1) {
+ entropy.entropy_count = 1;
+ }
+ entropy.buf_size = count;
+ if(ioctl(randfd, RNDADDENTROPY, &entropy) < 0) {
+ perror("RNDADDENTROPY");
+ return(1);
+ }
+ }
+
+ return(0);
+}
+
diff --git a/package/czechlight-cfg-fs/init-czechlight.sh b/package/czechlight-cfg-fs/init-czechlight.sh
index a550906..cb45f7b 100644
--- a/package/czechlight-cfg-fs/init-czechlight.sh
+++ b/package/czechlight-cfg-fs/init-czechlight.sh
@@ -46,4 +46,8 @@
/bin/cp -a /cfg/etc/* /etc/
fi
+if [ -f /cfg/random-seed/random-seed ]; then
+ cat /cfg/random-seed/random-seed | /sbin/czechlight-random-seed
+fi
+
exec /sbin/init
diff --git a/package/czechlight-rauc/rauc-hook.sh b/package/czechlight-rauc/rauc-hook.sh
index 9850c38..5b14883 100755
--- a/package/czechlight-rauc/rauc-hook.sh
+++ b/package/czechlight-rauc/rauc-hook.sh
@@ -4,7 +4,7 @@
slot-post-install)
case "$RAUC_SLOT_CLASS" in
cfg)
- for DIR in etc ssh-user-auth; do
+ for DIR in etc random-seed ssh-user-auth; do
if [[ -d /cfg/$DIR ]]; then
cp -a /cfg/$DIR ${RAUC_SLOT_MOUNT_POINT}/
fi