mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
sys: random: add fortuna PRNG
This commit is contained in:
parent
32413f872e
commit
99755eaa0c
10
Makefile.dep
10
Makefile.dep
@ -5,7 +5,8 @@ OLD_USEPKG := $(sort $(USEPKG))
|
||||
# include board dependencies
|
||||
-include $(RIOTBOARD)/$(BOARD)/Makefile.dep
|
||||
|
||||
# pull dependencies from drivers
|
||||
# pull dependencies from sys and drivers
|
||||
include $(RIOTBASE)/sys/Makefile.dep
|
||||
include $(RIOTBASE)/drivers/Makefile.dep
|
||||
|
||||
ifneq (,$(filter cbor_ctime,$(USEMODULE)))
|
||||
@ -615,6 +616,13 @@ ifneq (,$(filter random,$(USEMODULE)))
|
||||
USEMODULE += prng_tinymt32
|
||||
endif
|
||||
|
||||
ifneq (,$(filter prng_fortuna,$(USEMODULE)))
|
||||
USEMODULE += fortuna
|
||||
USEMODULE += hashes
|
||||
USEMODULE += crypto
|
||||
USEMODULE += xtimer
|
||||
endif
|
||||
|
||||
ifneq (,$(filter prng_tinymt32,$(USEMODULE)))
|
||||
USEMODULE += tinymt32
|
||||
endif
|
||||
|
3
sys/Makefile.dep
Normal file
3
sys/Makefile.dep
Normal file
@ -0,0 +1,3 @@
|
||||
ifneq (,$(filter prng_fortuna,$(USEMODULE)))
|
||||
CFLAGS += -DCRYPTO_AES
|
||||
endif
|
@ -21,6 +21,7 @@
|
||||
* - Mersenne Twister
|
||||
* - Simple Park-Miller PRNG
|
||||
* - Musl C PRNG
|
||||
* - Fortuna (CS)PRNG
|
||||
*/
|
||||
|
||||
#ifndef RANDOM_H
|
||||
|
@ -3,6 +3,10 @@ SRC := random.c
|
||||
BASE_MODULE := prng
|
||||
SUBMODULES := 1
|
||||
|
||||
ifneq (,$(filter prng_fortuna,$(USEMODULE)))
|
||||
DIRS += fortuna
|
||||
endif
|
||||
|
||||
ifneq (,$(filter prng_tinymt32,$(USEMODULE)))
|
||||
DIRS += tinymt32
|
||||
endif
|
||||
|
98
sys/random/fortuna.c
Normal file
98
sys/random/fortuna.c
Normal file
@ -0,0 +1,98 @@
|
||||
/**
|
||||
* Copyright (C) 2016-2018 Bas Stottelaar <basstottelaar@gmail.com>
|
||||
*
|
||||
* 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 sys_random
|
||||
* @{
|
||||
* @file
|
||||
*
|
||||
* @brief Glue-code for Fortuna PRNG.
|
||||
*
|
||||
* @author Bas Stottelaar <basstottelaar@gmail.com>
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include "log.h"
|
||||
#include "mutex.h"
|
||||
|
||||
#include "fortuna/fortuna.h"
|
||||
|
||||
/**
|
||||
* @brief This holds the PRNG state.
|
||||
*/
|
||||
static fortuna_state_t fortuna_state;
|
||||
|
||||
/**
|
||||
* @brief Initialize the PRNG with a given number of bytes.
|
||||
*/
|
||||
static void _init(uint8_t *in, size_t bytes)
|
||||
{
|
||||
fortuna_seed_t seed;
|
||||
|
||||
/* ensure a seed of proper length is available, which may not be the case
|
||||
with a small input */
|
||||
memset(seed, 0, sizeof(seed));
|
||||
|
||||
for (int i = 0; i < (int) bytes; i++) {
|
||||
seed[i % sizeof(seed)] ^= in[i];
|
||||
}
|
||||
|
||||
/* initialize the PRNG state */
|
||||
fortuna_init(&fortuna_state);
|
||||
|
||||
/* update the PRNG seed (seed will be overwritten by design!) */
|
||||
fortuna_update_seed(&fortuna_state, &seed);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wrapper for fortuna_random_data that supports reading more than
|
||||
* FORTUNA_RESEED_LIMIT and also checks the result.
|
||||
*/
|
||||
static void _read(uint8_t *out, size_t bytes)
|
||||
{
|
||||
do {
|
||||
/* read at most chunk bytes to not exhaust the state at once */
|
||||
size_t chunk = (bytes < FORTUNA_RESEED_LIMIT) ?
|
||||
bytes : FORTUNA_RESEED_LIMIT;
|
||||
|
||||
int res = fortuna_random_data(&fortuna_state, out, chunk);
|
||||
|
||||
if (res == -1) {
|
||||
LOG_ERROR("random: reading more bytes than allowed.\n");
|
||||
}
|
||||
else if (res == -2) {
|
||||
LOG_ERROR("random: PRNG not initialized.\n");
|
||||
}
|
||||
else if (res == -3) {
|
||||
LOG_ERROR("random: unknown error.\n");
|
||||
}
|
||||
|
||||
/* advance bytes and buffer */
|
||||
bytes -= chunk;
|
||||
out += chunk;
|
||||
} while (bytes > FORTUNA_RESEED_LIMIT);
|
||||
}
|
||||
|
||||
void random_init_by_array(uint32_t init_key[], int key_length)
|
||||
{
|
||||
_init((uint8_t *) init_key, sizeof(uint32_t) * key_length);
|
||||
}
|
||||
|
||||
void random_init(uint32_t s)
|
||||
{
|
||||
_init((uint8_t *) &s, sizeof(s));
|
||||
}
|
||||
|
||||
uint32_t random_uint32(void)
|
||||
{
|
||||
uint32_t data;
|
||||
|
||||
_read((uint8_t *) &data, sizeof(data));
|
||||
|
||||
return data;
|
||||
}
|
22
sys/random/fortuna/LICENSE.txt
Normal file
22
sys/random/fortuna/LICENSE.txt
Normal file
@ -0,0 +1,22 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Brandon Lin
|
||||
Copyright (c) 2016-2018 Bas Stottelaar
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
1
sys/random/fortuna/Makefile
Executable file
1
sys/random/fortuna/Makefile
Executable file
@ -0,0 +1 @@
|
||||
include $(RIOTBASE)/Makefile.base
|
274
sys/random/fortuna/fortuna.c
Executable file
274
sys/random/fortuna/fortuna.c
Executable file
@ -0,0 +1,274 @@
|
||||
/**
|
||||
* @brief Fortuna PRNG implementation.
|
||||
*
|
||||
* The MIT License applies to this software. See the included LICENSE.txt file
|
||||
* for more information.
|
||||
*/
|
||||
|
||||
#include "fortuna.h"
|
||||
|
||||
/**
|
||||
* @brief Helper to increment the 128-bit counter (see section 9.4).
|
||||
*/
|
||||
static inline void fortuna_increment_counter(fortuna_state_t *state)
|
||||
{
|
||||
state->gen.counter.split.l++;
|
||||
|
||||
/* on overflow of low, increment high */
|
||||
if (state->gen.counter.split.l == 0) {
|
||||
state->gen.counter.split.h++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Corresponds to section 9.4.2.
|
||||
*/
|
||||
static void fortuna_reseed(fortuna_state_t *state, const uint8_t *seed,
|
||||
size_t length)
|
||||
{
|
||||
sha256_context_t ctx;
|
||||
|
||||
sha256_init(&ctx);
|
||||
sha256_update(&ctx, state->gen.key, 32);
|
||||
sha256_update(&ctx, seed, length);
|
||||
sha256_final(&ctx, state->gen.key);
|
||||
|
||||
/* if the generator was unseeded, this will mark it as seeded */
|
||||
fortuna_increment_counter(state);
|
||||
|
||||
#if FORTUNA_CLEANUP
|
||||
memset(&ctx, 0, sizeof(ctx));
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Corresponds to section 9.4.3.
|
||||
*/
|
||||
static int fortuna_generate_blocks(fortuna_state_t *state, uint8_t *out,
|
||||
size_t blocks)
|
||||
{
|
||||
cipher_context_t cipher;
|
||||
|
||||
/* check if generator has been seeded */
|
||||
if (state->gen.counter.split.l == 0 && state->gen.counter.split.h == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* initialize cipher based on state */
|
||||
int res = aes_init(&cipher, state->gen.key, FORTUNA_AES_KEY_SIZE);
|
||||
|
||||
if (res != CIPHER_INIT_SUCCESS) {
|
||||
#if FORTUNA_CLEANUP
|
||||
memset(&cipher, 0, sizeof(cipher));
|
||||
#endif
|
||||
return -2;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < blocks; i++) {
|
||||
aes_encrypt(&cipher, state->gen.counter.bytes, out + (i * 16));
|
||||
fortuna_increment_counter(state);
|
||||
}
|
||||
|
||||
#if FORTUNA_CLEANUP
|
||||
memset(&cipher, 0, sizeof(cipher));
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Corresponds to section 9.4.4.
|
||||
*/
|
||||
static int fortuna_pseudo_random_data(fortuna_state_t *state, uint8_t *out,
|
||||
size_t bytes)
|
||||
{
|
||||
uint8_t buf[16];
|
||||
|
||||
#if FORTUNA_RESEED_LIMIT
|
||||
/* maximum number of bytes per read is FORTUNA_RESEED_LIMIT */
|
||||
if (bytes > FORTUNA_RESEED_LIMIT) {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* check if generator has been seeded */
|
||||
if (state->gen.counter.split.l == 0 && state->gen.counter.split.h == 0) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
/* generate blocks per 16 bytes */
|
||||
size_t blocks = bytes / 16;
|
||||
|
||||
if (fortuna_generate_blocks(state, out, blocks)) {
|
||||
#if FORTUNA_CLEANUP
|
||||
memset(buf, 0, sizeof(buf));
|
||||
#endif
|
||||
return -3;
|
||||
}
|
||||
|
||||
/* generate one block for the remaining bytes */
|
||||
size_t remaining = bytes % 16;
|
||||
|
||||
if (remaining) {
|
||||
if (fortuna_generate_blocks(state, buf, 1)) {
|
||||
#if FORTUNA_CLEANUP
|
||||
memset(buf, 0, sizeof(buf));
|
||||
#endif
|
||||
return -3;
|
||||
}
|
||||
|
||||
memcpy(out + (blocks * 16), buf, remaining);
|
||||
}
|
||||
|
||||
/* switch to a new key to avoid later compromises of this output */
|
||||
if (fortuna_generate_blocks(state, state->gen.key, 2)) {
|
||||
#if FORTUNA_CLEANUP
|
||||
memset(buf, 0, sizeof(buf));
|
||||
#endif
|
||||
return -3;
|
||||
}
|
||||
|
||||
#if FORTUNA_CLEANUP
|
||||
memset(buf, 0, sizeof(buf));
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Corresponds to section 9.4.1 and 9.5.4.
|
||||
*/
|
||||
int fortuna_init(fortuna_state_t *state)
|
||||
{
|
||||
/* set everything to zero, then initialize the pools */
|
||||
memset(state, 0, sizeof(fortuna_state_t));
|
||||
|
||||
for (int i = 0; i < (int) FORTUNA_POOLS; i++) {
|
||||
sha256_init(&state->pools[i].ctx);
|
||||
}
|
||||
|
||||
#if FORTUNA_RESEED_INTERVAL
|
||||
/* set last reseed to ensure initial time diff is correct */
|
||||
state->last_reseed = xtimer_now_usec64();
|
||||
#endif
|
||||
|
||||
#if FORTUNA_LOCK
|
||||
/* initialize the lock */
|
||||
mutex_init(&state->lock);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Corresponds to section 9.5.5.
|
||||
*/
|
||||
int fortuna_random_data(fortuna_state_t *state, uint8_t *out, size_t bytes)
|
||||
{
|
||||
uint8_t buf[FORTUNA_POOLS * 32];
|
||||
|
||||
#if FORTUNA_LOCK
|
||||
mutex_lock(&state->lock);
|
||||
#endif
|
||||
|
||||
/* reseed the generator if needed, before returning data */
|
||||
#if FORTUNA_RESEED_INTERVAL
|
||||
if (state->pools[0].len >= FORTUNA_MIN_POOL_SIZE &&
|
||||
(xtimer_now_usec64() - state->last_reseed) > FORTUNA_RESEED_INTERVAL) {
|
||||
#else
|
||||
if (state->pools[0].len >= FORTUNA_MIN_POOL_SIZE) {
|
||||
#endif
|
||||
state->reseeds++;
|
||||
size_t len = 0;
|
||||
|
||||
for (int i = 0; i < (int) FORTUNA_POOLS; i++) {
|
||||
if (state->reseeds | (1 << i)) {
|
||||
sha256_final(&state->pools[i].ctx, &buf[len]);
|
||||
sha256_init(&state->pools[i].ctx);
|
||||
state->pools[i].len = 0;
|
||||
|
||||
/* append length of SHA-256 hash */
|
||||
len += 32;
|
||||
}
|
||||
}
|
||||
|
||||
fortuna_reseed(state, buf, len);
|
||||
|
||||
#if FORTUNA_RESEED_INTERVAL
|
||||
state->last_reseed = xtimer_now_usec64();
|
||||
#endif
|
||||
|
||||
#if FORTUNA_CLEANUP
|
||||
memset(buf, 0, sizeof(buf));
|
||||
#endif
|
||||
}
|
||||
|
||||
/* read bytes from the generator */
|
||||
int res = fortuna_pseudo_random_data(state, out, bytes);
|
||||
|
||||
#if FORTUNA_LOCK
|
||||
mutex_unlock(&state->lock);
|
||||
#endif
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Corresponds to section 9.5.6.
|
||||
*/
|
||||
int fortuna_add_random_event(fortuna_state_t *state, const uint8_t *data,
|
||||
uint8_t length, uint8_t source, uint8_t pool)
|
||||
{
|
||||
if (length < 1 || length > 32) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pool >= FORTUNA_POOLS) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
#if FORTUNA_LOCK
|
||||
mutex_lock(&state->lock);
|
||||
#endif
|
||||
|
||||
uint8_t header[2];
|
||||
header[0] = source;
|
||||
header[1] = length;
|
||||
sha256_update(&state->pools[pool].ctx, header, 2);
|
||||
sha256_update(&state->pools[pool].ctx, (uint8_t *) data, length);
|
||||
state->pools[pool].len += length;
|
||||
|
||||
#if FORTUNA_LOCK
|
||||
mutex_unlock(&state->lock);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Corresponds to section 9.6.2.
|
||||
*/
|
||||
int fortuna_write_seed(fortuna_state_t *state, fortuna_seed_t *out)
|
||||
{
|
||||
return fortuna_random_data(state, (uint8_t *)out, FORTUNA_SEED_SIZE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Corresponds to section 9.6.2.
|
||||
*/
|
||||
int fortuna_update_seed(fortuna_state_t *state, fortuna_seed_t *inout)
|
||||
{
|
||||
#if FORTUNA_LOCK
|
||||
mutex_lock(&state->lock);
|
||||
#endif
|
||||
|
||||
/* reseed using the provided seed */
|
||||
fortuna_reseed(state, (uint8_t *)inout, FORTUNA_SEED_SIZE);
|
||||
|
||||
#if FORTUNA_LOCK
|
||||
mutex_unlock(&state->lock);
|
||||
#endif
|
||||
|
||||
/* the seed file must be overwritten by a new seed file */
|
||||
return fortuna_random_data(state, (uint8_t *)inout, FORTUNA_SEED_SIZE);
|
||||
}
|
232
sys/random/fortuna/fortuna.h
Executable file
232
sys/random/fortuna/fortuna.h
Executable file
@ -0,0 +1,232 @@
|
||||
/**
|
||||
* @brief Fortuna PRNG implementation.
|
||||
*
|
||||
* The MIT License applies to this software. See the included LICENSE.txt file
|
||||
* for more information.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is not your general purpose PRNG: it is hungry for memory.
|
||||
*
|
||||
* See https://www.schneier.com/cryptography/paperfiles/fortuna.pdf for the
|
||||
* implementation details. Code insipred by https://github.com/blin00/os (MIT
|
||||
* licensed), but heavily modified, stripped and improved for RIOT-OS.
|
||||
*
|
||||
* The implementation follows the paper, with a few exceptions:
|
||||
*
|
||||
* - Initialization of the generator and PRNG is combined in fortuna_init.
|
||||
* - The check if the generator is seeded is moved from fortuna_generate_blocks
|
||||
* to fortuna_pseudo_random_data for optimization reasons.
|
||||
* - In fortuna_random_data, the check on state->reseeds == 0 is not performed.
|
||||
* It would never provide a seed whenever the PRNG is initialized with a seed
|
||||
* file, when entropy sources are not available (yet). It would still fail
|
||||
* whenever fortuna_pseudo_random_data checks if the generator is seeded! See
|
||||
* https://crypto.stackexchange.com/q/56390 for more information.
|
||||
*/
|
||||
|
||||
#ifndef FORTUNA_H
|
||||
#define FORTUNA_H
|
||||
|
||||
#include "xtimer.h"
|
||||
#include "mutex.h"
|
||||
|
||||
#include "crypto/aes.h"
|
||||
#include "hashes/sha256.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @bief Number of pools to use, which may not exceed 32. More pools means more
|
||||
* memory usage, but makes it harder for an attacker to influence the
|
||||
* state. The recommended value is 32, as discussed in section 9.5.2.
|
||||
*/
|
||||
#ifndef FORTUNA_POOLS
|
||||
#define FORTUNA_POOLS (32U)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Minimum number of bytes that should be in a pool. Higher values will
|
||||
* delay reseeds even if good random entropy is collected. In section
|
||||
* 9.5.5, a suitable value of 64 bytes is suggested.
|
||||
*/
|
||||
#ifndef FORTUNA_MIN_POOL_SIZE
|
||||
#define FORTUNA_MIN_POOL_SIZE (64U)
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @brief Definition of the seed file size used to initialize the PRNG. The
|
||||
* default value of 64 bytes is suggested by section 9.6.1.
|
||||
*/
|
||||
#ifndef FORTUNA_SEED_SIZE
|
||||
#define FORTUNA_SEED_SIZE (64U)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Reseed interval in us. After this interval, the PRNG must be
|
||||
* reseeded. Per section 9.5.5, the recommended value is 100ms. Set to
|
||||
* zero to disable this security feature.
|
||||
*/
|
||||
#ifndef FORTUNA_RESEED_INTERVAL
|
||||
#define FORTUNA_RESEED_INTERVAL (0)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Reseed limit in bytes. After this number of bytes, the PRNG must be
|
||||
* reseeded. Per section 9.4.4, the recommended value is 2^20 bytes
|
||||
* (=1 MB). Set to zero to disable this security feature.
|
||||
*/
|
||||
#ifndef FORTUNA_RESEED_LIMIT
|
||||
#define FORTUNA_RESEED_LIMIT (1U << 20)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Fortuna requires a block cipher with a 256-bit key to minimize
|
||||
* permutation attacks.
|
||||
*
|
||||
* @note RIOT-OS does not (yet) support AES-256. Therefore, at the expense of
|
||||
* security, AES-128 is used instead. An detailed explanation on the
|
||||
* effects can be found at https://crypto.stackexchange.com/a/5736.
|
||||
*/
|
||||
#ifndef FORTUNA_AES_KEY_SIZE
|
||||
#define FORTUNA_AES_KEY_SIZE (16U)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Use a mutex to lock concurrent access when running sensitive
|
||||
* operations in multi-threaded applications.
|
||||
*/
|
||||
#ifndef FORTUNA_LOCK
|
||||
#define FORTUNA_LOCK (1)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief When set, perform additional instructions to clear temporary
|
||||
* variables to prevent leaking sensitive information.
|
||||
*/
|
||||
#ifndef FORTUNA_CLEANUP
|
||||
#define FORTUNA_CLEANUP (1)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Generator counter and key.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t key[32];
|
||||
union {
|
||||
struct {
|
||||
uint64_t l;
|
||||
uint64_t h;
|
||||
} split;
|
||||
uint8_t bytes[16];
|
||||
} counter;
|
||||
} fortuna_generator_t;
|
||||
|
||||
/**
|
||||
* @brief Pool for storing entropy.
|
||||
*/
|
||||
typedef struct {
|
||||
sha256_context_t ctx;
|
||||
uint32_t len;
|
||||
} fortuna_pool_t;
|
||||
|
||||
/**
|
||||
* @brief The Fortuna state.
|
||||
*/
|
||||
typedef struct {
|
||||
fortuna_generator_t gen;
|
||||
fortuna_pool_t pools[FORTUNA_POOLS];
|
||||
uint32_t reseeds;
|
||||
#if FORTUNA_RESEED_INTERVAL > 0
|
||||
uint64_t last_reseed;
|
||||
#endif
|
||||
#if FORTUNA_LOCK
|
||||
mutex_t lock;
|
||||
#endif
|
||||
} fortuna_state_t;
|
||||
|
||||
/**
|
||||
* @brief Type definition of a Fortuna seed file.
|
||||
*/
|
||||
typedef uint32_t fortuna_seed_t[FORTUNA_SEED_SIZE];
|
||||
|
||||
/**
|
||||
* @brief Initialize the Fortuna PRNG state.
|
||||
*
|
||||
* It is possible to use this method to clear an existing state.
|
||||
*
|
||||
* @param[inout] state PRNG state
|
||||
*
|
||||
* @return zero on succesful initialization
|
||||
* @return non-zero on error
|
||||
*/
|
||||
int fortuna_init(fortuna_state_t *state);
|
||||
|
||||
/**
|
||||
* @brief Read random bytes from the PRNG. The number of bytes may not exceed
|
||||
* FORTUNA_RESEED_LIMIT bytes.
|
||||
*
|
||||
* @param[inout] state PRNG state
|
||||
* @param[out] out pointer to buffer
|
||||
* @param[in] bytes number of bytes to write in buffer
|
||||
*
|
||||
* @return zero on success
|
||||
* @return -1 on reading more that FORTUNA_RESEED_LIMIT bytes
|
||||
* @return -2 on reading from unseeded PRNG
|
||||
* @return -3 on other error
|
||||
*/
|
||||
int fortuna_random_data(fortuna_state_t *state, uint8_t *out, size_t bytes);
|
||||
|
||||
/**
|
||||
* @brief Add a entropy of a random event to one PRNG pool. The pool must
|
||||
* exist and the source length must be 1-32 bytes.
|
||||
*
|
||||
* @param[inout] state PRNG state
|
||||
* @param[in] data pointer to entropy source
|
||||
* @param[in] length length of entropy source
|
||||
* @param[in] source source identifier (each source has its own ID)
|
||||
* @param[in] pool pool number to add entropy to
|
||||
*
|
||||
* @return zero on success
|
||||
* @return -1 on zero bytes or more than 32 bytes
|
||||
* @return -2 on invalid pool number
|
||||
*/
|
||||
int fortuna_add_random_event(fortuna_state_t *state, const uint8_t *data,
|
||||
uint8_t length, uint8_t source, uint8_t pool);
|
||||
|
||||
/**
|
||||
* @brief Generate 64 bytes from the PRNG and write that to an output
|
||||
* buffer for use on next startup.
|
||||
*
|
||||
* This method must be invoked before shutting down the PRNG (e.g. on system
|
||||
* shutdown).
|
||||
*
|
||||
* @param[inout] state PRNG state
|
||||
* @param[out] data pointer to output buffer for the seed
|
||||
*
|
||||
* @return zero on success
|
||||
*/
|
||||
int fortuna_write_seed(fortuna_state_t *state, fortuna_seed_t *out);
|
||||
|
||||
/**
|
||||
* @brief Reseed the PRNG using a seed. By design, this value will be
|
||||
* overwritten after use.
|
||||
*
|
||||
* This method should be invoked once on PRNG startup, in case a seed is
|
||||
* available.
|
||||
*
|
||||
* @param[inout] state PRNG state
|
||||
* @param[inout] data pointer to input and output buffer for the seed
|
||||
*
|
||||
* @return zero on success
|
||||
*/
|
||||
int fortuna_update_seed(fortuna_state_t *state, fortuna_seed_t *inout);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* FORTUNA_H */
|
||||
/** @} */
|
Loading…
Reference in New Issue
Block a user