1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/sys/include/entropy_source.h

307 lines
10 KiB
C

/*
* Copyright (C) 2020 HAW Hamburg
*
* 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.
*/
/**
* @defgroup sys_entropy_source_common Entropy Source Common
* @ingroup sys_entropy_source
* @brief Common definitions and functions for entropy sources
*
*
* @{
* @file
*
* @author Peter Kietzmann <peter.kietzmann@haw-hamburg.de>
*/
#ifndef ENTROPY_SOURCE_H
#define ENTROPY_SOURCE_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stddef.h>
#include <inttypes.h>
#include <assert.h>
/**
* @brief Entropy source error codes.
*/
typedef enum {
ENTROPY_SOURCE_OK = 0, /**< Success */
ENTROPY_SOURCE_ERR_INIT = -1, /**< Source initialization error */
ENTROPY_SOURCE_ERR_CONFIG = -2, /**< Source configuration error */
ENTROPY_SOURCE_ERR_TEST_REP = -3, /**< Repetition count test error */
ENTROPY_SOURCE_ERR_TEST_PROP = -4, /**< Adaptive proportion test error */
ENTROPY_SOURCE_ERR_TEST_BOTH = -5, /**< Repetition count and Adaptive
* proportion test error */
ENTROPY_SOURCE_ERR_COND = -6, /**< Conditioning error */
} entropy_source_error_t;
/**
* @brief Data structure for Repetition Count Test (NIST SP 800-90B 4.4.1).
*/
typedef struct {
uint8_t old_sample; /**< Preceding sample to compare for repetition */
uint16_t cnt_rep; /**< Counter to count repetition */
uint8_t c_rep; /**< Cutoff threshold */
} entropy_source_tests_rep_t;
/**
* @brief Data structure for Adaptive Proportion Test (NIST SP 800-90B 4.4.2).
*/
typedef struct {
uint8_t old_sample; /**< Preceding sample to compare for repetition */
uint16_t cnt_prop; /**< Counter to count proportion */
uint16_t cnt_window; /**< Counter to count window size */
uint16_t c_prop; /**< Cutoff threshold */
} entropy_source_tests_prop_t;
/**
* @brief Scale Min. Entropy to fixed point integer to avoid float. The
* entropy per sample (8 Byte) of a noise source can likely be smaller
* than 1 bit.
*/
#define ENTROPY_SOURCE_HMIN_SCALE(x) ((x * (1UL << 16)))
/**
* @brief Scale internal fixed point Min. Entropy back to float. This macro is
* not required and only there for convenience.
*/
#define ENTROPY_SOURCE_HMIN_SCALE_BACK(x) ((float)x / (1UL << 16))
/**
* @defgroup sys_entropy_source_config Entropy Source compile configurations
* @ingroup config
* @{
*/
/**
* @brief Window size for Adaptive Proportion Test (NIST SP 800-90B 4.4.2).
*
* In (NIST SP 800-90B 4.4.2) a window size of 512 samples is recommended for
* non-binary sources. Typically, RIOT use cases will not request as many
* samples, thus, it might be worth considering a smaller window size so the
* test is more likely to complete a cycle. It is noteworthy that a cutoff value
* calculated by @ref entropy_source_test_prop_cutoff that is greater than the
* window size may lead to undetected errors.
*/
#ifndef CONFIG_ENTROPY_SOURCE_TESTS_WIN
#define CONFIG_ENTROPY_SOURCE_TESTS_WIN (512)
#endif
/**
* @brief Abort factor for von Neumann extractor. The algorithms runs as long
* as no bit changes appear in subsequent samples. This define adds a
* factor that aborts the procedure after (factor * requested length)
* samples.
*/
#ifndef CONFIG_ENTROPY_SOURCE_NEUMANN_ABORT
#define CONFIG_ENTROPY_SOURCE_NEUMANN_ABORT (5)
#endif
/** @} */
/**
* @brief Get one sample of the entropy source.
*
* This function is typically used by the entropy source internally. A
* conditioning component might need an interface to request a variable number
* of samples, e.g., depending on the contained amount of entropy.
*
* @param[out] sample pointer to write sample to.
*
* @return ENTROPY_SOURCE_OK on success
* @return negative @ref entropy_source_error_t code on error
*/
typedef int (*entropy_source_sample_func_t)(uint8_t *sample);
/**
* @brief Applies von Neumann unbiasing.
*
* This function requests as many samples needed to create \p len unbiased bytes
* using \p func. The algorithm compares bits of consecutive samples. Only bit
* changes will be considered for the output value. An abort criterium stops
* sampling after (len * CONFIG_ENTROPY_SOURCE_NEUMANN_ABORT) iterations.
*
* @warning This function has a non-deterministic runtime.
*
* @param[in] func pointer to @ref entropy_source_sample_func_t function
that returns samples
* @param[out] out pointer to write unbiased bytes to
* @param[in] len number of bytes to generate
*
* @return ENTROPY_SOURCE_OK on success
* @return negative @ref entropy_source_error_t code on error
*/
int entropy_source_neumann_unbias(entropy_source_sample_func_t func,
uint8_t *out, size_t len);
/**
* @brief Calculate cutoff value for Repetition Count Test (NIST SP 800-90B 4.4.1)
*
*~~~~
* C = 1 + ( (-log2 a) / H)
*~~~~
*
* C: Cutoff value.
* H: Min. entropy of the source
* <a href="https://github.com/usnistgov/SP800-90B_EntropyAssessment">
* SP800-90B EntropyAssessment</a>.
* a: Probability of type I error. We assume 2^(-20).
*
* @param[in] entropy_per_sample Estimated min. entropy of one sample scaled
* by ENTROPY_SOURCE_HMIN_SCALE()
*
* @return Cutoff threshold
*/
static inline uint32_t entropy_source_test_rep_cutoff(uint32_t entropy_per_sample)
{
return (1 + ((20 * 65536) / entropy_per_sample));
}
/**
* @brief Calculate cutoff value for Adaptive Proportion Test
* (NIST SP 800-90B 4.4.2)
*
* @param[in] entropy_per_sample Estimated min. entropy of one sample scaled
* by ENTROPY_SOURCE_HMIN_SCALE()
*
* @return Cutoff value
* @return ENTROPY_SOURCE_ERR_CONFIG if parameter
invalid
*/
static inline int entropy_source_test_prop_cutoff(uint32_t entropy_per_sample)
{
int ret;
if (entropy_per_sample < 49152UL) { /* 0.75 bit/sample */
ret = 410;
}
else if (entropy_per_sample < 98304UL) { /* 1.5 bit/sample */
ret = 311;
}
else if (entropy_per_sample < 196608UL) { /* 3 bit/sample */
ret = 177;
}
else if (entropy_per_sample < 393216UL) { /* 6 bit/sample */
ret = 62;
}
else if (entropy_per_sample <= 524288UL) { /* 8 bit/sample */
ret = 13;
}
else {
ret = ENTROPY_SOURCE_ERR_CONFIG;
}
return ret;
}
/**
* @brief Initialize structure for Repetition Count Test
*
* @param[in, out] state Test structure of one entropy source.
* @param[in] c_rep Cutoff value calculated by
* @ref entropy_source_test_rep_cutoff.
*/
static inline void entropy_source_test_rep_init(
entropy_source_tests_rep_t *state, uint16_t c_rep)
{
assert(state != NULL);
state->old_sample = 0;
state->cnt_rep = 0;
state->c_rep = c_rep;
}
/**
* @brief Initialize structure for Adaptive Proportion Test
*
* @param[in, out] state Test structure of one entropy source.
* @param[in] c_prop Cutoff value calculated by
* @ref entropy_source_test_prop_cutoff.
*/
static inline void entropy_source_test_prop_init(
entropy_source_tests_prop_t *state, uint16_t c_prop)
{
assert(state != NULL);
state->old_sample = 0;
state->cnt_prop = 0;
state->cnt_window = CONFIG_ENTROPY_SOURCE_TESTS_WIN;
state->c_prop = c_prop;
}
/**
* @brief Performs Repetition Count Test (NIST SP 800-90B 4.4.1).
*
* This function will not block sampling. It only indicates detected errors.
*
* @param[in, out] state Test structure of one entropy source.
* @param[in] sample Current sample.
*
* @return ENTROPY_SOURCE_OK on success
* @return ENTROPY_SOURCE_ERR_TEST_REP on detected weakness
*/
int entropy_source_test_rep(entropy_source_tests_rep_t *state, uint8_t sample);
/**
* @brief Performs Adaptive Proportion Test (NIST SP 800-90B 4.4.2).
*
* This function will not block the sampling. It only indicates detected errors.
*
* @param[in, out] state Test structure of one entropy source.
* @param[in] sample current sample.
*
* @return ENTROPY_SOURCE_OK on success
* @return ENTROPY_SOURCE_ERR_TEST_PROP on detected weakness
*/
int entropy_source_test_prop(entropy_source_tests_prop_t *state,
uint8_t sample);
/**
* @brief Convenience function to perform @ref entropy_source_test_rep
* and @ref entropy_source_test_prop.
*
* This function will not block the sampling. It only indicates detected errors.
*
* @param[in, out] state_rep Repetition Count test structure of one
* entropy source.
* @param[in, out] state_prop Adaptive Proportion test structure of one
* entropy source.
* @param[in] sample Current sample.
*
* @return ENTROPY_SOURCE_OK on success
* @return negative @ref entropy_source_error_t code on error
*/
static inline int entropy_source_test(entropy_source_tests_rep_t *state_rep,
entropy_source_tests_prop_t *state_prop,
uint8_t sample)
{
int ret = ENTROPY_SOURCE_OK;
if (entropy_source_test_rep(state_rep, sample) < 0) {
ret = ENTROPY_SOURCE_ERR_TEST_REP;
}
if (entropy_source_test_prop(state_prop, sample) < 0) {
/* If repetition count failed before, indicate that both tests failed */
if (ret == ENTROPY_SOURCE_ERR_TEST_REP) {
ret = ENTROPY_SOURCE_ERR_TEST_BOTH;
}
else {
ret = ENTROPY_SOURCE_ERR_TEST_PROP;
}
}
return ret;
}
#ifdef __cplusplus
}
#endif
#endif /* ENTROPY_SOURCE_H */
/** @} */