[LEDE-DEV] [PATCH] urandom-seed: add initial implementation
John Crispin
john at phrozen.org
Fri Jun 3 04:19:07 PDT 2016
On 03/06/2016 13:15, Etienne Champetier wrote:
> Hi John,
>
> 2016-06-03 11:00 GMT+02:00 John Crispin <john at phrozen.org>:
>> 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.
>>
> see
> https://github.com/jedisct1/libsodium/issues/374
> and the link inside it
> http://crypto.stackexchange.com/questions/34019/on-linux-does-dev-random-unblocking-imply-that-dev-urandom-is-seeded
>
> apparently /dev/urandom is initialized first and then /dev/random, so
> we can poll()/select() on /dev/random and when it returns it means
> /dev/urandom is initialized, but is there any already available
> command to poll/select a file? (also i haven't double checked these
> findings)
> At the end of the second link you also see that minimum read on
> /dev/random is 64bits (so dd with size 1 bits will use 64bits)
>
> getrandom() was created for multiple good reasons, has clearly defined
> and safe behaviour so this is the way to go for me.
> I think we can afford 4K of binary (uncompressed) for a big step up in
> security :)
ok at rat-tail of possible problems
>
>> 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.
>
> what about ubox.git for getrandom, and base-files for the preinit and init?
>
ok, ubox.git is probably more appropriate
John
> if i have more time to kill i'll try to submit a getrandom like to
> busybox (but no promise)
>
>>
>> rest looks good on first glance, thanks for the effort.
>
> Your welcome, thanks for the review
>
>>
>> John
>>
>
> Etienne
>
>>
>>
>>> 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