diff --git a/arch/arm/src/common/up_initialize.c b/arch/arm/src/common/up_initialize.c index 973e2318f38..9e4477d76a1 100644 --- a/arch/arm/src/common/up_initialize.c +++ b/arch/arm/src/common/up_initialize.c @@ -198,6 +198,10 @@ void up_initialize(void) devnull_register(); /* Standard /dev/null */ #endif +#if defined(CONFIG_DEV_URANDOM) + devurandom_register(); /* Standard /dev/urandom */ +#endif + #if defined(CONFIG_DEV_ZERO) devzero_register(); /* Standard /dev/zero */ #endif diff --git a/arch/avr/src/common/up_initialize.c b/arch/avr/src/common/up_initialize.c index 4ac08dfd0b6..3290dab26ba 100644 --- a/arch/avr/src/common/up_initialize.c +++ b/arch/avr/src/common/up_initialize.c @@ -239,6 +239,10 @@ void up_initialize(void) devnull_register(); /* Standard /dev/null */ #endif +#if defined(CONFIG_DEV_URANDOM) + devurandom_register(); /* Standard /dev/urandom */ +#endif + #if defined(CONFIG_DEV_ZERO) devzero_register(); /* Standard /dev/zero */ #endif diff --git a/arch/hc/src/common/up_initialize.c b/arch/hc/src/common/up_initialize.c index a0173046476..fb953156623 100644 --- a/arch/hc/src/common/up_initialize.c +++ b/arch/hc/src/common/up_initialize.c @@ -165,6 +165,10 @@ void up_initialize(void) devnull_register(); /* Standard /dev/null */ #endif +#if defined(CONFIG_DEV_URANDOM) + devurandom_register(); /* Standard /dev/urandom */ +#endif + #if defined(CONFIG_DEV_ZERO) devzero_register(); /* Standard /dev/zero */ #endif diff --git a/arch/mips/src/common/up_initialize.c b/arch/mips/src/common/up_initialize.c index 940b3672e19..6b2384b8ba3 100644 --- a/arch/mips/src/common/up_initialize.c +++ b/arch/mips/src/common/up_initialize.c @@ -167,6 +167,10 @@ void up_initialize(void) devnull_register(); /* Standard /dev/null */ #endif +#if defined(CONFIG_DEV_URANDOM) + devurandom_register(); /* Standard /dev/urandom */ +#endif + #if defined(CONFIG_DEV_ZERO) devzero_register(); /* Standard /dev/zero */ #endif diff --git a/arch/rgmp/src/nuttx.c b/arch/rgmp/src/nuttx.c index ee6148e35e5..8e1b916b251 100644 --- a/arch/rgmp/src/nuttx.c +++ b/arch/rgmp/src/nuttx.c @@ -53,6 +53,8 @@ #include #include #include +#include +#include #include #include #include @@ -131,6 +133,32 @@ void up_initialize(void) syslog_initialize(SYSLOG_INIT_EARLY); + /* Register devices */ + +#if CONFIG_NFILE_DESCRIPTORS > 0 + +#if defined(CONFIG_DEV_NULL) + devnull_register(); /* Standard /dev/null */ +#endif + +#if defined(CONFIG_DEV_URANDOM) + devurandom_register(); /* Standard /dev/urandom */ +#endif + +#if defined(CONFIG_DEV_ZERO) + devzero_register(); /* Standard /dev/zero */ +#endif + +#if defined(CONFIG_DEV_LOOP) + loop_register(); /* Standard /dev/loop */ +#endif +#endif /* CONFIG_NFILE_DESCRIPTORS */ + +#if defined(CONFIG_SCHED_INSTRUMENTATION_BUFFER) && \ + defined(CONFIG_DRIVER_NOTE) + note_register(); /* Non-standard /dev/note */ +#endif + #if defined(CONFIG_CRYPTO) /* Initialize the HW crypto and /dev/crypto */ diff --git a/arch/sh/src/common/up_initialize.c b/arch/sh/src/common/up_initialize.c index c4389936555..528a7c903e7 100644 --- a/arch/sh/src/common/up_initialize.c +++ b/arch/sh/src/common/up_initialize.c @@ -156,6 +156,10 @@ void up_initialize(void) devnull_register(); /* Standard /dev/null */ #endif +#if defined(CONFIG_DEV_URANDOM) + devurandom_register(); /* Standard /dev/urandom */ +#endif + #if defined(CONFIG_DEV_ZERO) devzero_register(); /* Standard /dev/zero */ #endif diff --git a/arch/sim/src/up_initialize.c b/arch/sim/src/up_initialize.c index 5df82aec955..cc8c890ea69 100644 --- a/arch/sim/src/up_initialize.c +++ b/arch/sim/src/up_initialize.c @@ -153,6 +153,10 @@ void up_initialize(void) devnull_register(); /* Standard /dev/null */ #endif +#if defined(CONFIG_DEV_URANDOM) + devurandom_register(); /* Standard /dev/urandom */ +#endif + #if defined(CONFIG_DEV_ZERO) devzero_register(); /* Standard /dev/zero */ #endif diff --git a/arch/x86/src/common/up_initialize.c b/arch/x86/src/common/up_initialize.c index 6a9eca8d5ae..e3041739308 100644 --- a/arch/x86/src/common/up_initialize.c +++ b/arch/x86/src/common/up_initialize.c @@ -167,6 +167,10 @@ void up_initialize(void) devnull_register(); /* Standard /dev/null */ #endif +#if defined(CONFIG_DEV_URANDOM) + devurandom_register(); /* Standard /dev/urandom */ +#endif + #if defined(CONFIG_DEV_ZERO) devzero_register(); /* Standard /dev/zero */ #endif diff --git a/arch/z16/src/common/up_initialize.c b/arch/z16/src/common/up_initialize.c index 3f375763bd6..499e74966ec 100644 --- a/arch/z16/src/common/up_initialize.c +++ b/arch/z16/src/common/up_initialize.c @@ -167,6 +167,10 @@ void up_initialize(void) devnull_register(); /* Standard /dev/null */ #endif +#if defined(CONFIG_DEV_URANDOM) + devurandom_register(); /* Standard /dev/urandom */ +#endif + #if defined(CONFIG_DEV_ZERO) devzero_register(); /* Standard /dev/zero */ #endif diff --git a/arch/z80/src/common/up_initialize.c b/arch/z80/src/common/up_initialize.c index 760f6c74a95..1820871fbef 100644 --- a/arch/z80/src/common/up_initialize.c +++ b/arch/z80/src/common/up_initialize.c @@ -164,6 +164,10 @@ void up_initialize(void) devnull_register(); /* Standard /dev/null */ #endif +#if defined(CONFIG_DEV_URANDOM) + devurandom_register(); /* Standard /dev/urandom */ +#endif + #if defined(CONFIG_DEV_ZERO) devzero_register(); /* Standard /dev/zero */ #endif diff --git a/drivers/Kconfig b/drivers/Kconfig index bc506ee1e00..819183c4806 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -30,6 +30,13 @@ config DEV_RANDOM default y depends on ARCH_HAVE_RNG +config DEV_URANDOM + bool "Enable /dev/urandom" + default n + ---help--- + xorshift128 is a pseudorandom number generator that's simple, + portable, and can also be used on 8-bit and 16-bit MCUs. + source drivers/loop/Kconfig menu "Buffering" diff --git a/drivers/Makefile b/drivers/Makefile index ff0a00b5b5a..cf97712926e 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -98,6 +98,10 @@ endif ifeq ($(CONFIG_PWM),y) CSRCS += pwm.c endif + +ifeq ($(CONFIG_DEV_URANDOM),y) + CSRCS += dev_urandom.c +endif endif AOBJS = $(ASRCS:.S=$(OBJEXT)) diff --git a/drivers/dev_urandom.c b/drivers/dev_urandom.c new file mode 100644 index 00000000000..6a5e48a9323 --- /dev/null +++ b/drivers/dev_urandom.c @@ -0,0 +1,245 @@ +/**************************************************************************** + * drivers/dev_urandom.c + * + * Copyright (C) 2016 Gregory Nutt. All rights reserved. + * Author: David S. Alessio + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* This random number generator is simple, fast and portable. + * Ref: https://en.wikipedia.org/wiki/Xorshift + */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +typedef union +{ + struct + { + uint32_t x; + uint32_t y; + uint32_t z; + uint32_t w; + }; + uint8_t u[16]; +} xorshift128_state_t; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +#define min(a, b) (((a) < (b)) ? (a) : (b)) + +static ssize_t devurand_read(FAR struct file *filep, FAR char *buffer, + size_t buflen); +static ssize_t devurand_write(FAR struct file *filep, FAR const char *buffer, + size_t buflen); +#ifndef CONFIG_DISABLE_POLL +static int devurand_poll(FAR struct file *filep, FAR struct pollfd *fds, + bool setup); +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct file_operations devurand_fops = +{ + NULL, /* open */ + NULL, /* close */ + devurand_read, /* read */ + devurand_write, /* write */ + NULL, /* seek */ + NULL /* ioctl */ +#ifndef CONFIG_DISABLE_POLL + , devurand_poll /* poll */ +#endif +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS + , NULL /* unlink */ +#endif +}; + +static xorshift128_state_t prng; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static uint32_t xorshift128(void) +{ + uint32_t t = prng.x; + + t ^= t << 11; + t ^= t >> 8; + + prng.x = prng.y; + prng.y = prng.z; + prng.z = prng.w; + + prng.w ^= prng.w >> 19; + prng.w ^= t; + + return prng.w; +} + +/**************************************************************************** + * Name: devurand_read + ****************************************************************************/ + +static ssize_t devurand_read(FAR struct file *filep, FAR char *buffer, + size_t len) +{ + size_t n; + uint32_t rnd; + + n = len; + + /* Align buffer pointer to 4-byte boundry */ + + if ((unsigned)buffer & 0x03) + { + /* Generate a pseudo random number */ + + rnd = xorshift128(); + + while ((unsigned)buffer & 0x03) + { + if (n <= 0) + { + return len; + } + + *buffer++ = rnd & 0xFF; + rnd >>= 8; + --n; + } + } + + /* Stuff buffer with PRNGs 4 bytes at a time */ + + while (n >= 4) + { + *(uint32_t *) buffer = xorshift128(); + buffer += 4; + n -= 4; + } + + /* Stuff remaining 1, 2, or 3 bytes */ + + if (n > 0) + { + /* Generate a pseudo random number */ + + rnd = xorshift128(); + + do + { + *buffer++ = rnd & 0xFF; + rnd >>= 8; + } + while (--n > 0); + } + + return len; +} + +/**************************************************************************** + * Name: devurand_write + ****************************************************************************/ + +static ssize_t devurand_write(FAR struct file *filep, FAR const char *buffer, + size_t len) +{ + /* Write can be used to seed the PRNG state */ + + len = min(len, sizeof(prng.u)); + memcpy(&prng.u, buffer, len); + return len; +} + +/**************************************************************************** + * Name: devurand_poll + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_POLL +static int devurand_poll(FAR struct file *filep, FAR struct pollfd *fds, + bool setup) +{ + if (setup) + { + fds->revents |= (fds->events & (POLLIN | POLLOUT)); + if (fds->revents != 0) + { + sem_post(fds->sem); + } + } + + return OK; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: devurandom_register + * + * Description: + * Register /dev/urandom + * + ****************************************************************************/ + +void devurandom_register(void) +{ + /* Seed the PRNG */ + + prng.w = 97; + prng.x = 101; + prng.y = prng.w << 17; + prng.z = prng.x << 25; + + (void)register_driver("/dev/urandom", &devurand_fops, 0666, NULL); +} diff --git a/include/nuttx/fs/fs.h b/include/nuttx/fs/fs.h index 03f62f976a6..ea0409cd84d 100644 --- a/include/nuttx/fs/fs.h +++ b/include/nuttx/fs/fs.h @@ -1013,6 +1013,16 @@ int fdesc_poll(int fd, FAR struct pollfd *fds, bool setup); void devnull_register(void); +/**************************************************************************** + * Name: devurandom_register + * + * Description: + * Register /dev/urandom + * + ****************************************************************************/ + +void devurandom_register(void); + /**************************************************************************** * Name: devcrypto_register *