diff --git a/cpu/native/include/native_internal.h b/cpu/native/include/native_internal.h index b784de8b26..8a54ef9a43 100644 --- a/cpu/native/include/native_internal.h +++ b/cpu/native/include/native_internal.h @@ -145,6 +145,8 @@ extern const char *_progname; extern char **_native_argv; extern pid_t _native_pid; extern pid_t _native_id; +extern unsigned _native_rng_seed; +extern int _native_rng_mode; /**< 0 = /dev/random, 1 = random(3) */ extern const char *_native_unix_socket_path; #ifdef MODULE_UART0 diff --git a/cpu/native/periph/random.c b/cpu/native/periph/random.c index 427a1f2e75..ebe7730d4f 100644 --- a/cpu/native/periph/random.c +++ b/cpu/native/periph/random.c @@ -8,6 +8,7 @@ /** * @ingroup native_cpu + * @defgroup native_rng * @{ * * @author Ludwig Ortmann @@ -16,6 +17,9 @@ #include #include #include +#include +#include + #include "cpu-conf.h" #include "native_internal.h" @@ -26,10 +30,40 @@ #include "debug.h" static int powered = 0; +static int dev_random = -1; + +/********************************************************************** + * internal API declaration + **********************************************************************/ + +/** + * seed host random module with @ref _native_rng_seed + */ +void _native_rng_init_det(void); +void _native_rng_init_hq(void); +unsigned _native_rng_read_det(char *buf, unsigned num); +unsigned _native_rng_read_hq(char *buf, unsigned num); + +/********************************************************************** + * public API implementation + **********************************************************************/ void random_init(void) { - DEBUGF("random_init: powering on\n"); + DEBUG("random_init: initializing\n"); + switch (_native_rng_mode) { + case 0: + _native_rng_init_hq(); + break; + case 1: + _native_rng_init_det(); + break; + default: + err(EXIT_FAILURE, "random_init: _native_rng_mode is in invalid state %i\n", + _native_rng_mode); + break; + } + DEBUG("random_init: powering on\n"); random_poweron(); } @@ -40,31 +74,89 @@ int random_read(char *buf, unsigned int num) return 0; } - DEBUGF("random_read: writing %ui bytes\n", num); + DEBUG("random_read: writing %u bytes\n", num); + switch (_native_rng_mode) { + case 0: + num = _native_rng_read_hq(buf, num); + break; + case 1: + num = _native_rng_read_det(buf, num); + break; + default: + num = 0; + err(EXIT_FAILURE, "random_read: _native_rng_mode is in invalid state %i\n", + _native_rng_mode); + break; + } + return num; +} + +void random_poweron(void) +{ + DEBUG("random_poweron: power on\n"); + powered = 1; +} + +void random_poweroff(void) +{ + DEBUG("random_poweroff: power off\n"); + powered = 0; +} + +/********************************************************************** + * internal API implementation + **********************************************************************/ + +void _native_rng_init_det(void) +{ + DEBUG("_native_rng_init_det\n"); + _native_syscall_enter(); + real_srandom(_native_rng_seed); + _native_syscall_leave(); +} + +void _native_rng_init_hq(void) +{ + DEBUG("_native_rng_init_hq\n"); + _native_syscall_enter(); + dev_random = real_open("/dev/random", O_RDONLY); + if (dev_random == -1) { + err(EXIT_FAILURE, "_native_rng_init_hq: open(/dev/random)"); + } + _native_syscall_leave(); +} + +unsigned _native_rng_read_det(char *buf, unsigned num) +{ + DEBUG("_native_rng_read_det\n"); for (unsigned i = 0; i < num; i++) { _native_syscall_enter(); buf[i] = (char)real_random(); _native_syscall_leave(); } + return num; } -/** - * seed host random module with @ref _native_id - */ -void random_poweron(void) +unsigned _native_rng_read_hq(char *buf, unsigned num) { - DEBUGF("random_poweron: power on\n"); - powered = 1; - _native_syscall_enter(); - real_srandom((unsigned int)_native_id); - _native_syscall_leave(); -} + DEBUG("_native_rng_read_hq\n"); + unsigned offset = 0; -void random_poweroff(void) -{ - DEBUGF("random_poweroff: power off\n"); - powered = 0; + while (num > 0) { + _native_syscall_enter(); + int r = real_read(dev_random, (buf + offset), num); + _native_syscall_leave(); + + if (r == -1) { + err(EXIT_FAILURE, "_native_rng_read_hq: read"); + } + + num -= r; + offset += r; + } + + return offset; } /** diff --git a/cpu/native/startup.c b/cpu/native/startup.c index 0d5137a6af..ed899aa01a 100644 --- a/cpu/native/startup.c +++ b/cpu/native/startup.c @@ -43,6 +43,8 @@ const char *_progname; char **_native_argv; pid_t _native_pid; pid_t _native_id; +unsigned _native_rng_seed = 0; +int _native_rng_mode = 0; const char *_native_unix_socket_path = NULL; /** @@ -202,6 +204,8 @@ void usage_exit(void) #endif real_printf("\ -i specify instance id (set by config module)\n\ +-s specify srandom(3) seed (/dev/random is used instead of\n\ + random(3) if the option is omitted)\n\ -d daemonize\n\ -e redirect stderr to file\n\ -E do not redirect stderr (i.e. leave sterr unchanged despite\n\ @@ -262,6 +266,16 @@ __attribute__((constructor)) static void startup(int argc, char **argv) } _native_id = atol(argv[argp]); } + else if (strcmp("-s", arg) == 0) { + if (argp + 1 < argc) { + argp++; + } + else { + usage_exit(); + } + _native_rng_seed = atol(argv[argp]); + _native_rng_mode = 1; + } else if (strcmp("-d", arg) == 0) { if (strcmp(stdiotype, "stdio") == 0) { stdiotype = "null";