mirror of
https://github.com/apache/nuttx.git
synced 2026-05-20 04:16:35 +08:00
This change provides an option to add /dev/urandom to all architectures. The pseudo-random algorithm I choose strikes an arguably-good balance between being "random" and small/fast enough for 8/16 bit MCUs. It’s the well-documented xorshift128 algorithm. It has an internal state of 128 bits that can be [re-]seeded with a write.
This commit is contained in:
committed by
Gregory Nutt
parent
91ba0be667
commit
6cefbc0c3f
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -53,6 +53,8 @@
|
||||
#include <nuttx/sched.h>
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/fs/fs.h>
|
||||
#include <nuttx/sched_note.h>
|
||||
#include <nuttx/serial/pty.h>
|
||||
#include <nuttx/syslog/syslog.h>
|
||||
#include <nuttx/crypto/crypto.h>
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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 <nuttx/config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <poll.h>
|
||||
#include <errno.h>
|
||||
#include <nuttx/fs/fs.h>
|
||||
|
||||
/****************************************************************************
|
||||
* 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);
|
||||
}
|
||||
@@ -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
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user