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