Skip to content

Commit

Permalink
cpu/native: add high-quality random implementation
Browse files Browse the repository at this point in the history
Per default random data is read from `/dev/random` now.

If specified (e.g. `-s 4711`), data is generated by calls to POSIX
random function like before. The POSIX random API is initialize with
the given seed (`srandom(4711);` in this example).
  • Loading branch information
LudwigKnuepfer committed Jan 14, 2015
1 parent 52cc7eb commit 88fa49a
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 14 deletions.
2 changes: 2 additions & 0 deletions cpu/native/include/native_internal.h
Expand Up @@ -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
Expand Down
120 changes: 106 additions & 14 deletions cpu/native/periph/random.c
Expand Up @@ -8,6 +8,7 @@

/**
* @ingroup native_cpu
* @defgroup native_rng
* @{
*
* @author Ludwig Ortmann <ludwig.ortmann@fu-berlin.de>
Expand All @@ -16,6 +17,9 @@
#include <string.h>
#include <stdlib.h>
#include <err.h>
#include <sys/stat.h>
#include <fcntl.h>


#include "cpu-conf.h"
#include "native_internal.h"
Expand All @@ -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();
}

Expand All @@ -40,33 +74,91 @@ int random_read(char *buf, unsigned int num)
return 0;
}

DEBUGF("random_read: writing %ui bytes\n", num);
for (unsigned i = 0; i < num; i++) {
_native_syscall_enter();
buf[i] = (char)real_random();
_native_syscall_leave();
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;
}

/**
* seed host random module with @ref _native_id
*/
void random_poweron(void)
{
DEBUGF("random_poweron: power on\n");
DEBUG("random_poweron: power on\n");
powered = 1;
_native_syscall_enter();
real_srandom((unsigned int)_native_id);
_native_syscall_leave();
}

void random_poweroff(void)
{
DEBUGF("random_poweroff: power off\n");
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;
}

unsigned _native_rng_read_hq(char *buf, unsigned num)
{
DEBUG("_native_rng_read_hq\n");
unsigned offset = 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;
}

/**
* @}
*/
14 changes: 14 additions & 0 deletions cpu/native/startup.c
Expand Up @@ -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;

/**
Expand Down Expand Up @@ -202,6 +204,8 @@ void usage_exit(void)
#endif
real_printf("\
-i <id> specify instance id (set by config module)\n\
-s <seed> 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\
Expand Down Expand Up @@ -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";
Expand Down

0 comments on commit 88fa49a

Please sign in to comment.