You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

182 lines
4.1 KiB

/*
* Copyright (C) 2014 Ludwig Knüpfer <ludwig.knuepfer@fu-berlin.de>
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup native_cpu
* @defgroup native_rng
* @{
*
* @author Ludwig Knüpfer <ludwig.knuepfer@fu-berlin.de>
*/
#include <string.h>
#include <stdlib.h>
#include <err.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "cpu_conf.h"
#include "native_internal.h"
#include "periph/random.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
static int powered = 0;
static int initialized = 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)
{
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;
}
initialized = 1;
DEBUG("random_init: powering on\n");
random_poweron();
}
int random_read(char *buf, unsigned int num)
{
if (!initialized) {
warnx("random_read: random device not initialized, failing\n");
return 0;
}
if (!powered) {
warnx("random_read: random device not powered, failing\n");
return 0;
}
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:
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");
if (!initialized) {
warnx("random_poweron: not initialized.");
}
powered = 1;
}
void random_poweroff(void)
{
DEBUG("random_poweroff: power off\n");
if (!initialized) {
warnx("random_poweroff: not initialized.");
}
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;
}
/**
* @}
*/