[LEDE-DEV] [PATCH] urandom-seed: add initial implementation

John Crispin john at phrozen.org
Fri Jun 3 02:00:03 PDT 2016


Hi Etienne,

comment inline ...

On 02/06/2016 23:21, Etienne CHAMPETIER wrote:
> This package:
> 1) seed /dev/urandom with a saved seed as early as possible
>     (using /lib/preinit/81_urandom_seed)
> 2) save a new seed using getrandom() so we are sure /dev/urandom
>    pool is initialized (using /etc/init.d/urandom_seed)
> 
> seed size is 512 bytes (ie /proc/sys/kernel/random/poolsize / 8)
> it's the same size as in ubuntu 14.04 and all systemd systems
> 
> seed file is /etc/urandom.seed (need a writable path)
> 
> seeding /dev/urandom doesn't change entropy estimation, so we still have
> "random: ubus urandom read with 4 bits of entropy available"
> messages in the logs, but we can now ignore them
> 
> Once tested on enough configuration (jffs2/ext4/ubifs/...)
> this package should be added to DEFAULT_PACKAGES
> 
> We could also add an urandom.seed at build time to improve first boot
> 
> Signed-off-by: Etienne CHAMPETIER <champetier.etienne at gmail.com>
> ---
>  package/utils/urandom-seed/Makefile                | 53 ++++++++++++++++++++
>  .../urandom-seed/files/81_urandom_seed.preinit     | 15 ++++++
>  package/utils/urandom-seed/files/getrandom.c       | 58 ++++++++++++++++++++++
>  package/utils/urandom-seed/files/urandom_seed.init | 19 +++++++
>  4 files changed, 145 insertions(+)
>  create mode 100644 package/utils/urandom-seed/Makefile
>  create mode 100644 package/utils/urandom-seed/files/81_urandom_seed.preinit
>  create mode 100644 package/utils/urandom-seed/files/getrandom.c
>  create mode 100644 package/utils/urandom-seed/files/urandom_seed.init
> 
> diff --git a/package/utils/urandom-seed/Makefile b/package/utils/urandom-seed/Makefile
> new file mode 100644
> index 0000000..ac58bfc
> --- /dev/null
> +++ b/package/utils/urandom-seed/Makefile
> @@ -0,0 +1,53 @@
> +#
> +# Copyright (C) 2016 Etienne CHAMPETIER <champetier.etienne at gmail.com>
> +#
> +# This is free software, licensed under the GNU General Public License v2.
> +# See /LICENSE for more information.
> +#
> +
> +include $(TOPDIR)/rules.mk
> +
> +PKG_NAME:=urandom-seed
> +PKG_RELEASE:=1
> +PKG_LICENSE:=GPL-2.0
> +PKG_LICENSE_FILES:=COPYING
> +PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)_$(PKG_RELEASE)
> +PKG_FLAGS:=nonshared
> +
> +include $(INCLUDE_DIR)/package.mk
> +
> +define Package/urandom-seed
> +  SECTION:=utils
> +  CATEGORY:=Base system
> +  TITLE:=Seed /dev/urandom on startup
> +  MAINTAINER:=Etienne CHAMPETIER <champetier.etienne at gmail.com>
> +endef
> +
> +define Package/urandom-seed/description
> +This package takes care of loading a previously saved seed into /dev/urandom,
> +and save a new seed from getrandom()
> +endef
> +
> +define Build/Prepare
> +	mkdir -p $(PKG_BUILD_DIR)
> +endef
> +
> +define Build/Configure
> +endef
> +
> +define Build/Compile
> +	$(TARGET_CC) $(TARGET_CFLAGS) ./files/getrandom.c -o $(PKG_BUILD_DIR)/getrandom
> +endef
> +
> +define Package/urandom-seed/install
> +	$(INSTALL_DIR) $(1)/usr/bin
> +	$(INSTALL_BIN) $(PKG_BUILD_DIR)/getrandom $(1)/usr/bin/
> +
> +	$(INSTALL_DIR) $(1)/lib/preinit
> +	$(INSTALL_DATA) ./files/81_urandom_seed.preinit $(1)/lib/preinit/81_urandom_seed
> +
> +	$(INSTALL_DIR) $(1)/etc/init.d
> +	$(INSTALL_BIN) ./files/urandom_seed.init $(1)/etc/init.d/urandom_seed
> +endef
> +
> +$(eval $(call BuildPackage,urandom-seed))
> diff --git a/package/utils/urandom-seed/files/81_urandom_seed.preinit b/package/utils/urandom-seed/files/81_urandom_seed.preinit
> new file mode 100644
> index 0000000..27ff587
> --- /dev/null
> +++ b/package/utils/urandom-seed/files/81_urandom_seed.preinit
> @@ -0,0 +1,15 @@
> +#!/bin/sh
> +
> +do_urandom_seed() {
> +    S=/etc/urandom.seed
> +    U=/dev/urandom
> +
> +    [ -c $U ] || { echo "Something is wrong with $U"; return; }
> +    [ -f $S ] || { echo "Seed file not found: $S"; return; }
> +    [ -O $S -a -G $S -a ! -x $S ] || { echo "Wrong owner / permissions for $S"; return; }
> +
> +    echo "Seeding $U with $S"
> +    cat $S > $U
> +}
> +
> +boot_hook_add preinit_main do_urandom_seed
> diff --git a/package/utils/urandom-seed/files/getrandom.c b/package/utils/urandom-seed/files/getrandom.c
> new file mode 100644
> index 0000000..2093ef8
> --- /dev/null
> +++ b/package/utils/urandom-seed/files/getrandom.c
> @@ -0,0 +1,58 @@
> +/*
> + * Copyright (C) 2016 Etienne Champetier <champetier.etienne at gmail.com>
> + *
> + * 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.
> + */
> +#define _GNU_SOURCE
> +#include <errno.h>
> +#include <linux/random.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <sys/syscall.h>
> +#include <unistd.h>
> +
> +#define ERROR_EXIT(fmt, ...) do { \
> +        fprintf(stderr, fmt, ## __VA_ARGS__); \
> +        return EXIT_FAILURE; \
> +        } while (0)
> +
> +int usage(char *name)
> +{
> +    fprintf(stderr, "Usage: %s <nb>\n", name);
> +    fprintf(stderr, " => return <nb> bytes from getrandom()\n");
> +    return EXIT_FAILURE;
> +}
> +
> +int main(int argc, char *argv[])
> +{
> +    if (argc != 2)
> +        return usage(argv[0]);
> +
> +    if (isatty(STDOUT_FILENO))
> +        ERROR_EXIT("Not outputting random to a tty\n");
> +
> +    int nbtot = atoi(argv[1]);
> +    if (nbtot < 1)
> +        ERROR_EXIT("Invalid <nb> param (must be > 0)\n");
> +
> +    char buf[256];
> +    int len = sizeof(buf);
> +    while (nbtot > 0) {
> +        if (nbtot <= sizeof(buf))
> +            len = nbtot;
> +        if (syscall(SYS_getrandom, buf, len, 0) == -1)
> +            ERROR_EXIT("getrandom() failed: %s\n", strerror(errno));
> +        if (write(STDOUT_FILENO, buf, len) != len)
> +            ERROR_EXIT("write() failed: %s\n", strerror(errno));
> +        nbtot -= sizeof(buf);
> +    }
> +}

i was wondering if we really need this extra tool to do the job. i see
you are using the new get_random syscall. i assume there is no other way
to get that randomness from the userland using a script ? normally i
would go for /dev/(u)random but obvioulsy that is not possible here.

if we really need this tool, i would prefer to just integrate it into
the procd.git tree to avoid having an extra package. we would want to
always install it anyhow.

rest looks good on first glance, thanks for the effort.

	John



> diff --git a/package/utils/urandom-seed/files/urandom_seed.init b/package/utils/urandom-seed/files/urandom_seed.init
> new file mode 100644
> index 0000000..b2aba28
> --- /dev/null
> +++ b/package/utils/urandom-seed/files/urandom_seed.init
> @@ -0,0 +1,19 @@
> +#!/bin/sh /etc/rc.common
> +
> +START=99
> +
> +SEED=/etc/urandom.seed
> +
> +save_seed() {
> +    touch $SEED.tmp
> +    chown root:root $SEED.tmp
> +    chmod 600 $SEED.tmp
> +    getrandom 512 > $SEED.tmp
> +
> +    logger "Saving urandom seed to $SEED"
> +    mv $SEED.tmp $SEED
> +}
> +
> +boot() {
> +    save_seed
> +}
> 



More information about the Lede-dev mailing list