sys/entropy_source: add new module for entropy sources
This commit is contained in:
parent
c337089de5
commit
aec75b55fe
@ -12,6 +12,7 @@ rsource "benchmark/Kconfig"
|
||||
rsource "color/Kconfig"
|
||||
rsource "div/Kconfig"
|
||||
rsource "embunit/Kconfig"
|
||||
rsource "entropy_source/Kconfig"
|
||||
rsource "event/Kconfig"
|
||||
rsource "fmt/Kconfig"
|
||||
rsource "isrpipe/Kconfig"
|
||||
|
||||
@ -706,6 +706,13 @@ ifneq (,$(filter conn_can,$(USEMODULE)))
|
||||
USEMODULE += xtimer
|
||||
endif
|
||||
|
||||
ifneq (,$(filter entropy_source_%,$(USEMODULE)))
|
||||
USEMODULE += entropy_source
|
||||
ifneq (,$(filter entropy_source_adc_noise,$(USEMODULE)))
|
||||
FEATURES_REQUIRED += periph_adc
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq (,$(filter puf_sram,$(USEMODULE)))
|
||||
USEMODULE += hashes
|
||||
USEMODULE += random
|
||||
|
||||
37
sys/entropy_source/Kconfig
Normal file
37
sys/entropy_source/Kconfig
Normal file
@ -0,0 +1,37 @@
|
||||
# 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.
|
||||
|
||||
menuconfig KCONFIG_USEMODULE_ENTROPY_SOURCE
|
||||
bool "Configure entropy sources"
|
||||
depends on USEMODULE_ENTROPY_SOURCE_ADC_NOISE || USEMODULE_ENTROPY_SOURCE_ZERO_ENTROPY
|
||||
help
|
||||
Configure entropy sources using Kconfig.
|
||||
|
||||
if KCONFIG_USEMODULE_ENTROPY_SOURCE
|
||||
|
||||
config ENTROPY_SOURCE_TESTS_WIN
|
||||
int "Window size for Adaptive Proportion Test"
|
||||
default 512
|
||||
depends on ENTROPY_SOURCE_ADC_HEALTH_TEST || ENTROPY_SOURCE_ZERO_HEALTH_TEST
|
||||
help
|
||||
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.
|
||||
|
||||
config ENTROPY_SOURCE_NEUMANN_ABORT
|
||||
int "Abort factor for von Neumann extractor"
|
||||
default 5
|
||||
help
|
||||
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.
|
||||
|
||||
rsource "adc_noise/Kconfig"
|
||||
rsource "zero_entropy/Kconfig"
|
||||
|
||||
endif # KCONFIG_USEMODULE_ENTROPY_SOURCE
|
||||
9
sys/entropy_source/Makefile
Normal file
9
sys/entropy_source/Makefile
Normal file
@ -0,0 +1,9 @@
|
||||
ifneq (,$(filter entropy_source_zero_entropy,$(USEMODULE)))
|
||||
DIRS += zero_entropy
|
||||
endif
|
||||
|
||||
ifneq (,$(filter entropy_source_adc_noise,$(USEMODULE)))
|
||||
DIRS += adc_noise
|
||||
endif
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
||||
77
sys/entropy_source/adc_noise/Kconfig
Normal file
77
sys/entropy_source/adc_noise/Kconfig
Normal file
@ -0,0 +1,77 @@
|
||||
# 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.
|
||||
|
||||
menuconfig KCONFIG_USEMODULE_ENTROPY_SOURCE_ADC_NOISE
|
||||
bool "Configure ADC Noise entropy source module"
|
||||
depends on USEMODULE_ENTROPY_SOURCE_ADC_NOISE
|
||||
help
|
||||
Configure the ADC Noise entropy source using Kconfig.
|
||||
|
||||
if KCONFIG_USEMODULE_ENTROPY_SOURCE_ADC_NOISE
|
||||
|
||||
choice
|
||||
bool "ADC default sampling resolution"
|
||||
default ENTROPY_SOURCE_ADC_RES_10BIT
|
||||
help
|
||||
This parameter sets the ADC sampling resolution. Please note that not all
|
||||
platforms support every value.
|
||||
|
||||
config ENTROPY_SOURCE_ADC_RES_6BIT
|
||||
bool "6 Bit"
|
||||
|
||||
config ENTROPY_SOURCE_ADC_RES_8BIT
|
||||
bool "8 Bit"
|
||||
|
||||
config ENTROPY_SOURCE_ADC_RES_10BIT
|
||||
bool "10 Bit"
|
||||
|
||||
config ENTROPY_SOURCE_ADC_RES_12BIT
|
||||
bool "12 Bit"
|
||||
|
||||
config ENTROPY_SOURCE_ADC_RES_14BIT
|
||||
bool "14 Bit"
|
||||
|
||||
config ENTROPY_SOURCE_ADC_RES_16BIT
|
||||
bool "16 Bit"
|
||||
|
||||
endchoice
|
||||
|
||||
config ENTROPY_SOURCE_ADC_LINE_NUM
|
||||
int "ADC line"
|
||||
range 0 16
|
||||
default 0
|
||||
help
|
||||
The ADC line maps to an I/O pin. This number acts as index to an array
|
||||
of predefined ADC devices that contain the pin definition. Typically,
|
||||
the array is defined by a board in a periph_conf.h file. Please note that
|
||||
a board is not required to specify a minimum number of lines.
|
||||
|
||||
config ENTROPY_SOURCE_ADC_HMIN
|
||||
int "Estimated entropy per sample [2^16 * bit/sample]"
|
||||
range 1 524288
|
||||
default 0
|
||||
help
|
||||
The entropy value needs to be estimated and evaluated thoroughly before
|
||||
deployment! To avoid float, the entropy value per one byte sample needs
|
||||
to be manually multiplied by 2^16 before configuring it (e.g., to
|
||||
an entropy value of 1 bit/sample, a value of 1 * 65536 needs to be set) .
|
||||
We default to zero which is an invalid configuration to enforce a
|
||||
thoughtful investigation on the actual entropy properties.
|
||||
|
||||
config ENTROPY_SOURCE_ADC_HEALTH_TEST
|
||||
bool "Enable health test"
|
||||
help
|
||||
Health tests are performed on every sample, if enabled. Thus, they
|
||||
slow down the entropy gathering process. Detected failures are reported by return
|
||||
value but they do not stop execution.
|
||||
|
||||
config ENTROPY_SOURCE_ADC_COND
|
||||
bool "Enable conditioning"
|
||||
help
|
||||
Conditioning increases runtime of the entropy generation process. Currently, a von
|
||||
Neumann extractor is involved which has an nondeterministic runtime.
|
||||
|
||||
endif # KCONFIG_USEMODULE_ENTROPY_SOURCE_ADC_NOISE
|
||||
3
sys/entropy_source/adc_noise/Makefile
Executable file
3
sys/entropy_source/adc_noise/Makefile
Executable file
@ -0,0 +1,3 @@
|
||||
MODULE := entropy_source_adc_noise
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
||||
90
sys/entropy_source/adc_noise/adc_noise.c
Normal file
90
sys/entropy_source/adc_noise/adc_noise.c
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
/**
|
||||
* @ingroup sys_entropy_source_adc
|
||||
*
|
||||
* @{
|
||||
* @file
|
||||
*
|
||||
* @author Peter Kietzmann <peter.kietzmann@haw-hamburg.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include "periph/adc.h"
|
||||
#include "entropy_source.h"
|
||||
#include "entropy_source/adc_noise.h"
|
||||
|
||||
entropy_source_tests_rep_t adc_state_rep;
|
||||
entropy_source_tests_prop_t adc_state_prop;
|
||||
|
||||
static int _get_sample(uint8_t *out)
|
||||
{
|
||||
int ret = ENTROPY_SOURCE_OK;
|
||||
uint8_t byte = 0;
|
||||
|
||||
for (unsigned bit = 0; bit < 8; bit++) {
|
||||
int sample = adc_sample(CONFIG_ENTROPY_SOURCE_ADC_LINE,
|
||||
CONFIG_ENTROPY_SOURCE_ADC_RES);
|
||||
if (sample < 0) {
|
||||
/* Resolution is not applicable */
|
||||
return ENTROPY_SOURCE_ERR_CONFIG;
|
||||
}
|
||||
/* use LSB of each ADC sample and shift it to build a value */
|
||||
byte |= (uint8_t)(sample & 0x01) << bit;
|
||||
}
|
||||
/* copy generated byte to out */
|
||||
*out = byte;
|
||||
|
||||
if (IS_ACTIVE(CONFIG_ENTROPY_SOURCE_ADC_HEALTH_TEST)) {
|
||||
ret = entropy_source_test(&adc_state_rep, &adc_state_prop, byte);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int entropy_source_adc_init(void)
|
||||
{
|
||||
/* init ADC */
|
||||
if (adc_init(CONFIG_ENTROPY_SOURCE_ADC_LINE) != 0) {
|
||||
return ENTROPY_SOURCE_ERR_INIT;
|
||||
}
|
||||
|
||||
if (IS_ACTIVE(CONFIG_ENTROPY_SOURCE_ADC_HEALTH_TEST)) {
|
||||
unsigned int cutoff;
|
||||
cutoff = entropy_source_test_rep_cutoff(CONFIG_ENTROPY_SOURCE_ADC_HMIN);
|
||||
entropy_source_test_rep_init(&adc_state_rep, cutoff);
|
||||
cutoff = entropy_source_test_prop_cutoff(CONFIG_ENTROPY_SOURCE_ADC_HMIN);
|
||||
entropy_source_test_prop_init(&adc_state_prop, cutoff);
|
||||
}
|
||||
|
||||
return ENTROPY_SOURCE_OK;
|
||||
}
|
||||
|
||||
int entropy_source_adc_get(uint8_t *out, size_t len)
|
||||
{
|
||||
assert(out != NULL);
|
||||
|
||||
int ret = ENTROPY_SOURCE_OK;
|
||||
|
||||
if (IS_ACTIVE(CONFIG_ENTROPY_SOURCE_ADC_COND)) {
|
||||
entropy_source_sample_func_t p = &_get_sample;
|
||||
ret = entropy_source_neumann_unbias(p, out, len);
|
||||
}
|
||||
else {
|
||||
for (unsigned iter = 0; iter < len; iter++) {
|
||||
int tmp = _get_sample(&out[iter]);
|
||||
/* Remember the worst failure during
|
||||
* sampling multiple values to return */
|
||||
if (tmp < ret) {
|
||||
ret = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
46
sys/entropy_source/doc.txt
Normal file
46
sys/entropy_source/doc.txt
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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 Entropy Sources
|
||||
* @ingroup sys
|
||||
* @brief Collection of different Entropy Sources
|
||||
* @warning Entropy sources need to be thoroughly evaluated before deployment!
|
||||
* @experimental This API is in an early state - expect changes.
|
||||
* @note This API is considered as internal. Only use it if you know what
|
||||
* you are doing and expect API changes without deprecation.
|
||||
*
|
||||
*
|
||||
* @brief Collection of entropy sources.
|
||||
*
|
||||
*
|
||||
* This module adds support for additional entropy sources next to pure peripheral sources like
|
||||
* @ref drivers_periph_hwrng and @ref sys_puf_sram. The concepts implemented here are heavily
|
||||
* influenced by NIST SP 800-90B. Entropy sources can be used to feed more advanced entropy
|
||||
* modules for cryptographic purposes, which typically accumulate multiple sources and safely
|
||||
* maintain internal sates. Alternatively, these sources can be used directly or with internal
|
||||
* conditioning enabled for non-cryptographic tasks like seed generation of general purpose PRNGs,
|
||||
* in the absence of a hardware random number generator. The API, however, is not meant to face a user.
|
||||
*
|
||||
* A common component provides optional access to health tests and conditioning
|
||||
* (@ref sys_entropy_source_config) that can be run on
|
||||
* parallel instantiations. The conditioning currently implements a von Neumann extractor to
|
||||
* unbias samples. It adds a variable runtime (dependent on the input samples) but is lightweight.
|
||||
* In future, other conditioning mechanisms such as hash based derivation functions might be
|
||||
* included.
|
||||
*
|
||||
* Entropy sources require thorough testing and evaluation for serious deployments which is out of
|
||||
* scope of this module, and we refer to <a href="https://github.com/usnistgov/
|
||||
* SP800-90B_EntropyAssessment">SP800-90B_EntropyAssessment</a> for validation. Among other metrics,
|
||||
* this tool will return an entropy estimation per sample that should be employed for every
|
||||
* deployment scenario and must be configured in software accordingly. In the specific case
|
||||
* of the ADC based entropy source, a developer needs to set @ref CONFIG_ENTROPY_SOURCE_ADC_HMIN
|
||||
* accordingly.
|
||||
*
|
||||
*/
|
||||
125
sys/entropy_source/entropy_source.c
Normal file
125
sys/entropy_source/entropy_source.c
Normal file
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
/**
|
||||
* @ingroup sys_entropy_source_common
|
||||
*
|
||||
* @{
|
||||
* @file
|
||||
*
|
||||
* @author Peter Kietzmann <peter.kietzmann@haw-hamburg.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "entropy_source.h"
|
||||
|
||||
int entropy_source_neumann_unbias(entropy_source_sample_func_t func,
|
||||
uint8_t *out, size_t len)
|
||||
{
|
||||
assert(func != NULL && out != NULL);
|
||||
|
||||
uint8_t old_sample, new_sample, sample_out = 0;
|
||||
uint8_t bit1, bit2, bit_pos = 0;
|
||||
size_t bytes_count = 0;
|
||||
size_t sample_count = 0;
|
||||
size_t abort = len * CONFIG_ENTROPY_SOURCE_NEUMANN_ABORT;
|
||||
int tmp, ret = ENTROPY_SOURCE_OK;
|
||||
|
||||
/* Get initial sample */
|
||||
tmp = func(&old_sample);
|
||||
|
||||
/* Only return in case of failed configuration */
|
||||
if (ret == ENTROPY_SOURCE_ERR_CONFIG) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
while (bytes_count < len) {
|
||||
/* Increment sample counter and abort if
|
||||
* exceeds maximum number of iterations */
|
||||
sample_count++;
|
||||
if (sample_count > abort) {
|
||||
return ENTROPY_SOURCE_ERR_COND;
|
||||
}
|
||||
|
||||
/* Get next sample */
|
||||
tmp = func(&new_sample);
|
||||
|
||||
/* Remember the worst failure during
|
||||
* sampling multiple values to return */
|
||||
if (tmp < ret) {
|
||||
ret = tmp;
|
||||
}
|
||||
|
||||
/* Iterate each bit in sample */
|
||||
for (unsigned j = 0; j < 8; j++) {
|
||||
bit1 = (1 << j) & old_sample;
|
||||
bit2 = (1 << j) & new_sample;
|
||||
|
||||
/* Only save information if change occurred
|
||||
* 0/1 change results in 1
|
||||
* 1/0 change results in 0
|
||||
*/
|
||||
if (bit1 < bit2) {
|
||||
sample_out |= (1 << bit_pos++);
|
||||
}
|
||||
else if (bit1 > bit2) {
|
||||
sample_out &= ~(1 << bit_pos++);
|
||||
}
|
||||
|
||||
/* Once 8 bits have been gathered, write to output */
|
||||
if (bit_pos == 8) {
|
||||
out[bytes_count] = sample_out;
|
||||
bit_pos = 0;
|
||||
bytes_count++;
|
||||
}
|
||||
}
|
||||
/* Store recent sample for next iteration */
|
||||
old_sample = new_sample;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int entropy_source_test_rep(entropy_source_tests_rep_t *state, uint8_t sample)
|
||||
{
|
||||
assert(state != NULL);
|
||||
|
||||
if (sample == state->old_sample && state->cnt_rep > 0) {
|
||||
state->cnt_rep++;
|
||||
if (state->cnt_rep >= state->c_rep) {
|
||||
return ENTROPY_SOURCE_ERR_TEST_REP;
|
||||
}
|
||||
}
|
||||
else {
|
||||
state->old_sample = sample;
|
||||
state->cnt_rep = 1;
|
||||
}
|
||||
return ENTROPY_SOURCE_OK;
|
||||
}
|
||||
|
||||
int entropy_source_test_prop(entropy_source_tests_prop_t *state, uint8_t sample)
|
||||
{
|
||||
assert(state != NULL);
|
||||
|
||||
if (state->cnt_window == CONFIG_ENTROPY_SOURCE_TESTS_WIN) {
|
||||
state->old_sample = sample;
|
||||
state->cnt_prop = 0;
|
||||
state->cnt_window = 0;
|
||||
}
|
||||
else {
|
||||
state->cnt_window++;
|
||||
if (state->old_sample == sample) {
|
||||
state->cnt_prop++;
|
||||
}
|
||||
if (state->cnt_prop >= state->c_prop) {
|
||||
return ENTROPY_SOURCE_ERR_TEST_PROP;
|
||||
}
|
||||
}
|
||||
return ENTROPY_SOURCE_OK;
|
||||
}
|
||||
35
sys/entropy_source/zero_entropy/Kconfig
Normal file
35
sys/entropy_source/zero_entropy/Kconfig
Normal file
@ -0,0 +1,35 @@
|
||||
# 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.
|
||||
|
||||
menuconfig KCONFIG_USEMODULE_ENTROPY_SOURCE_ZERO_ENTROPY
|
||||
bool "Configure zero entropy source module"
|
||||
depends on USEMODULE_ENTROPY_SOURCE_ZERO_ENTROPY
|
||||
help
|
||||
Configure the zero entropy source using Kconfig.
|
||||
|
||||
if KCONFIG_USEMODULE_ENTROPY_SOURCE_ZERO_ENTROPY
|
||||
|
||||
config ENTROPY_SOURCE_ZERO_HMIN
|
||||
int "Estimated entropy per sample (byte)"
|
||||
default 58982
|
||||
help
|
||||
This is a dummy default value for testing. The zero entropy module does not
|
||||
contain any entropy at all.
|
||||
|
||||
config ENTROPY_SOURCE_ZERO_HEALTH_TEST
|
||||
bool "Enable health test"
|
||||
default y
|
||||
help
|
||||
Enable health test by default. Testing is the only purpose of this module.
|
||||
|
||||
config ENTROPY_SOURCE_ZERO_COND
|
||||
bool "Enable conditioning"
|
||||
help
|
||||
Disable conditioning by default. Conditioning is useless for zeros only. The von
|
||||
Neumann extractor would never finish and wait for the stop criterion given by
|
||||
@ref CONFIG_ENTROPY_SOURCE_NEUMANN_ABORT.
|
||||
|
||||
endif # KCONFIG_USEMODULE_ENTROPY_SOURCE_ZERO_ENTROPY
|
||||
3
sys/entropy_source/zero_entropy/Makefile
Executable file
3
sys/entropy_source/zero_entropy/Makefile
Executable file
@ -0,0 +1,3 @@
|
||||
MODULE := entropy_source_zero_entropy
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
||||
72
sys/entropy_source/zero_entropy/zero_entropy.c
Normal file
72
sys/entropy_source/zero_entropy/zero_entropy.c
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
/**
|
||||
* @ingroup sys_entropy_source_zero
|
||||
* @{
|
||||
* @file
|
||||
*
|
||||
* @author Peter Kietzmann <peter.kietzmann@haw-hamburg.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include "kernel_defines.h"
|
||||
#include "entropy_source.h"
|
||||
#include "entropy_source/zero_entropy.h"
|
||||
|
||||
entropy_source_tests_rep_t zero_state_rep;
|
||||
entropy_source_tests_prop_t zero_state_prop;
|
||||
|
||||
static int _get_sample(uint8_t *out)
|
||||
{
|
||||
int ret = ENTROPY_SOURCE_OK;
|
||||
uint8_t byte = 0;
|
||||
|
||||
*out = byte;
|
||||
|
||||
if (IS_ACTIVE(CONFIG_ENTROPY_SOURCE_ZERO_HEALTH_TEST)) {
|
||||
ret = entropy_source_test(&zero_state_rep, &zero_state_prop, byte);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int entropy_source_zero_init(void)
|
||||
{
|
||||
if (IS_ACTIVE(CONFIG_ENTROPY_SOURCE_ZERO_HEALTH_TEST)) {
|
||||
unsigned int cutoff;
|
||||
cutoff = entropy_source_test_rep_cutoff(CONFIG_ENTROPY_SOURCE_ZERO_HMIN);
|
||||
entropy_source_test_rep_init(&zero_state_rep, cutoff);
|
||||
cutoff = entropy_source_test_prop_cutoff(CONFIG_ENTROPY_SOURCE_ZERO_HMIN);
|
||||
entropy_source_test_prop_init(&zero_state_prop, cutoff);
|
||||
}
|
||||
|
||||
return ENTROPY_SOURCE_OK;
|
||||
}
|
||||
|
||||
int entropy_source_zero_get(uint8_t *out, size_t len)
|
||||
{
|
||||
assert(out != NULL);
|
||||
|
||||
int ret = ENTROPY_SOURCE_OK;
|
||||
|
||||
if (IS_ACTIVE(CONFIG_ENTROPY_SOURCE_ZERO_COND)) {
|
||||
ret = entropy_source_neumann_unbias(_get_sample, out, len);
|
||||
}
|
||||
else {
|
||||
for (unsigned iter = 0; iter < len; iter++) {
|
||||
int tmp = _get_sample(&out[iter]);
|
||||
/* Remember the worst failure during
|
||||
* sampling multiple values to return */
|
||||
if (tmp < ret) {
|
||||
ret = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
306
sys/include/entropy_source.h
Normal file
306
sys/include/entropy_source.h
Normal file
@ -0,0 +1,306 @@
|
||||
/*
|
||||
* 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 */
|
||||
/** @} */
|
||||
158
sys/include/entropy_source/adc_noise.h
Normal file
158
sys/include/entropy_source/adc_noise.h
Normal file
@ -0,0 +1,158 @@
|
||||
/*
|
||||
* 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_adc ADC Noise Entropy Source
|
||||
* @ingroup sys_entropy_source
|
||||
* @brief Entropy Source based on LSB of ADC samples
|
||||
*
|
||||
*
|
||||
* This module provides entropy from ADC samples. Thereby, only the LSB is considered for
|
||||
* generation of output values. The available resolution as well as internal sampling rates,
|
||||
* specific driver settings and device inaccuracies may lead to different behavior between
|
||||
* different platforms. The configured ADC pin might be unconnected and floating,
|
||||
* it can be exposed as an I/O pin or internally connected to a thermal noise source, an
|
||||
* avalanche diode circuit or the receive path of an antenna. The possibilities are manifold,
|
||||
* thus, configuration and deployment properties of this module need to be thoroughly
|
||||
* validated.
|
||||
*
|
||||
* @note It is worth noting that ADC pins are typically vulnerable when physically
|
||||
* accessible. Developers should consider additional tamper detection concepts
|
||||
* and enclosures.
|
||||
*
|
||||
* @{
|
||||
* @file
|
||||
*
|
||||
* @author Peter Kietzmann <peter.kietzmann@haw-hamburg.de>
|
||||
*/
|
||||
|
||||
#ifndef ENTROPY_SOURCE_ADC_NOISE_H
|
||||
#define ENTROPY_SOURCE_ADC_NOISE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "periph/adc.h"
|
||||
|
||||
/**
|
||||
* @ingroup sys_entropy_source_config
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief ADC resolution default configuration.
|
||||
*/
|
||||
#if IS_ACTIVE(CONFIG_ENTROPY_SOURCE_ADC_RES_6BIT)
|
||||
#define CONFIG_ENTROPY_SOURCE_ADC_RES ADC_RES_6BIT
|
||||
#elif IS_ACTIVE(CONFIG_ENTROPY_SOURCE_ADC_RES_8BIT)
|
||||
#define CONFIG_ENTROPY_SOURCE_ADC_RES ADC_RES_8BIT
|
||||
#elif IS_ACTIVE(CONFIG_ENTROPY_SOURCE_ADC_RES_10BIT)
|
||||
#define CONFIG_ENTROPY_SOURCE_ADC_RES ADC_RES_10BIT
|
||||
#elif IS_ACTIVE(CONFIG_ENTROPY_SOURCE_ADC_RES_12BIT)
|
||||
#define CONFIG_ENTROPY_SOURCE_ADC_RES ADC_RES_12BIT
|
||||
#elif IS_ACTIVE(CONFIG_ENTROPY_SOURCE_ADC_RES_14BIT)
|
||||
#define CONFIG_ENTROPY_SOURCE_ADC_RES ADC_RES_14BIT
|
||||
#elif IS_ACTIVE(CONFIG_ENTROPY_SOURCE_ADC_RES_16BIT)
|
||||
#define CONFIG_ENTROPY_SOURCE_ADC_RES ADC_RES_16BIT
|
||||
#endif
|
||||
#ifndef CONFIG_ENTROPY_SOURCE_ADC_RES
|
||||
#define CONFIG_ENTROPY_SOURCE_ADC_RES ADC_RES_10BIT
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief ADC line default configuration.
|
||||
*
|
||||
* The ADC line maps to an I/O pin. This number acts as index to an array
|
||||
* of predefined ADC devices that contain the pin definition. Typically,
|
||||
* the array is defined by a board in a periph_conf.h file. Please note that
|
||||
* a board is not required to specify a minimum number of lines.
|
||||
*/
|
||||
#ifdef CONFIG_ENTROPY_SOURCE_ADC_LINE_NUM
|
||||
#define CONFIG_ENTROPY_SOURCE_ADC_LINE ADC_LINE(CONFIG_ENTROPY_SOURCE_ADC_LINE_NUM)
|
||||
#else
|
||||
#define CONFIG_ENTROPY_SOURCE_ADC_LINE ADC_LINE(0)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief ADC estimated entropy per sample [2^16 * bit/sample].
|
||||
*
|
||||
* The entropy value needs to be estimated and evaluated thoroughly beforehand
|
||||
* deployment! To avoid float, the
|
||||
* actual entropy value per one byte sample needs to be manually multiplied by
|
||||
* 2^16 before before configuring it (e.g., to
|
||||
* an entropy value of 1 bit/sample, a value of 1 * 65536 needs to be set) .
|
||||
* We default to zero which is an invalid configuration to enforce a
|
||||
* thoughtful investigation on the actual entropy properties. See
|
||||
* @ref sys_entropy_source for further information about entropy source
|
||||
* validation.
|
||||
*/
|
||||
#if !defined(CONFIG_KCONFIG_USEMODULE_ENTROPY_SOURCE_ADC_NOISE) || defined(DOXYGEN)
|
||||
#ifndef CONFIG_ENTROPY_SOURCE_ADC_HMIN
|
||||
#define CONFIG_ENTROPY_SOURCE_ADC_HMIN (0) /**< H_min=0 bit/sample * 2^16
|
||||
* is invalid and needs to
|
||||
* set manually!
|
||||
*/
|
||||
#endif /* !CONFIG_ENTROPY_SOURCE_ADC_HMIN */
|
||||
|
||||
#ifndef CONFIG_ENTROPY_SOURCE_ADC_HEALTH_TEST
|
||||
#define CONFIG_ENTROPY_SOURCE_ADC_HEALTH_TEST 0 /**< Disable ADC health test
|
||||
* by default.
|
||||
*/
|
||||
#endif
|
||||
#ifndef CONFIG_ENTROPY_SOURCE_ADC_COND
|
||||
#define CONFIG_ENTROPY_SOURCE_ADC_COND 0 /**< Disable ADC conditioning
|
||||
* test by default.
|
||||
*/
|
||||
#endif
|
||||
#endif /* !CONFIG_KCONFIG_USEMODULE_ENTROPY_SOURCE_ADC_NOISE || DOXYGEN */
|
||||
|
||||
/* Throw warning if H_min has not been re-configured */
|
||||
#if !CONFIG_ENTROPY_SOURCE_ADC_HMIN
|
||||
#warning The min. provided entropy must be set before using this module
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Initialize ADC and test structures, if tests are enabled.
|
||||
*
|
||||
* @return ENTROPY_SOURCE_OK on success
|
||||
* @return ENTROPY_SOURCE_ERR_INIT on ADC initialization failure
|
||||
*/
|
||||
int entropy_source_adc_init(void);
|
||||
|
||||
/**
|
||||
* @brief Generates bytes from ADC noise
|
||||
*
|
||||
* @param[out] buf pointer to write noisy 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_adc_get(uint8_t *buf, size_t len);
|
||||
|
||||
/**
|
||||
* @brief Static entropy per sample value for this source
|
||||
* [bit/sample * 2^16]
|
||||
*
|
||||
* @return entropy per sample
|
||||
*/
|
||||
static inline uint32_t entropy_source_adc_entropy_per_sample(void)
|
||||
{
|
||||
return CONFIG_ENTROPY_SOURCE_ADC_HMIN;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ENTROPY_SOURCE_ADC_NOISE_H */
|
||||
/** @} */
|
||||
92
sys/include/entropy_source/zero_entropy.h
Normal file
92
sys/include/entropy_source/zero_entropy.h
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* 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_zero Zero Entropy Source
|
||||
* @ingroup sys_entropy_source
|
||||
* @brief Zero Entropy Source for testing.
|
||||
*
|
||||
* This module produces zeros only and should be used for testing purposes only.
|
||||
*
|
||||
* @{
|
||||
* @file
|
||||
*
|
||||
* @author Peter Kietzmann <peter.kietzmann@haw-hamburg.de>
|
||||
*/
|
||||
|
||||
#ifndef ENTROPY_SOURCE_ZERO_ENTROPY_H
|
||||
#define ENTROPY_SOURCE_ZERO_ENTROPY_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/**
|
||||
* @ingroup sys_entropy_source_config
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Min. Entropy value for zero entropy module.
|
||||
*
|
||||
* H_min=0.9 bit/sample * 2^16 fake for testing!
|
||||
*/
|
||||
#if !defined(CONFIG_KCONFIG_USEMODULE_ENTROPY_SOURCE_ZERO_ENTROPY) || defined(DOXYGEN)
|
||||
#ifndef CONFIG_ENTROPY_SOURCE_ZERO_ENTROPY_HMIN
|
||||
#define CONFIG_ENTROPY_SOURCE_ZERO_HMIN (58982)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enable health test by default.
|
||||
*
|
||||
* Testing is the only purpose of this module.
|
||||
*/
|
||||
#ifndef CONFIG_ENTROPY_SOURCE_ZERO_HEALTH_TEST
|
||||
#define CONFIG_ENTROPY_SOURCE_ZERO_HEALTH_TEST 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Disable conditioning by default.
|
||||
*
|
||||
* Conditioning is useless for zeros only. The von Neumann extractor would
|
||||
* never finish and wait for the stop criterion given by
|
||||
* @ref CONFIG_ENTROPY_SOURCE_NEUMANN_ABORT.
|
||||
*/
|
||||
#ifndef CONFIG_ENTROPY_SOURCE_ZERO_COND
|
||||
#define CONFIG_ENTROPY_SOURCE_ZERO_COND 0
|
||||
#endif
|
||||
#endif /* !CONFIG_KCONFIG_USEMODULE_ENTROPY_SOURCE_ZERO_ENTROPY || DOXYGEN */
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Initializes test structures, if tests are enabled.
|
||||
*
|
||||
* @return ENTROPY_SOURCE_OK always
|
||||
*/
|
||||
int entropy_source_zero_init(void);
|
||||
|
||||
/**
|
||||
* @brief Generates zeros.
|
||||
*
|
||||
* @param[out] buf pointer to write zeros 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_zero_get(uint8_t *buf, size_t len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ENTROPY_SOURCE_ZERO_ENTROPY_H */
|
||||
/** @} */
|
||||
10
tests/entropy_source/Makefile
Normal file
10
tests/entropy_source/Makefile
Normal file
@ -0,0 +1,10 @@
|
||||
DEVELHELP ?= 0
|
||||
include ../Makefile.tests_common
|
||||
|
||||
BOARD ?= native
|
||||
|
||||
USEMODULE += fmt
|
||||
USEMODULE += entropy_source_zero_entropy
|
||||
USEMODULE += xtimer
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
||||
13
tests/entropy_source/Makefile.board.dep
Normal file
13
tests/entropy_source/Makefile.board.dep
Normal file
@ -0,0 +1,13 @@
|
||||
# Only include adc noise source if BOARD has an adc
|
||||
FEATURES_OPTIONAL += periph_adc
|
||||
|
||||
ifneq (,$(filter periph_adc,$(FEATURES_USED)))
|
||||
USEMODULE += entropy_source_adc_noise
|
||||
ifndef CONFIG_KCONFIG_USEMODULE_ENTROPY_SOURCE_ADC_NOISE
|
||||
# set a dummy default value for the provided amount of entropy
|
||||
CFLAGS += -DCONFIG_ENTROPY_SOURCE_ADC_HMIN=65536
|
||||
# enable ADC health tests and conditioning
|
||||
CFLAGS += -DCONFIG_ENTROPY_SOURCE_ADC_COND=1
|
||||
CFLAGS += -DCONFIG_ENTROPY_SOURCE_ADC_HEALTH_TEST=1
|
||||
endif
|
||||
endif
|
||||
62
tests/entropy_source/README.md
Normal file
62
tests/entropy_source/README.md
Normal file
@ -0,0 +1,62 @@
|
||||
# About
|
||||
This test compiles and runs entropy sources. The first `zero entropy` source can be run on
|
||||
`native` and does not provide real entropy values, though, it tests execution of the main
|
||||
module and its common components including the optional health tests. Additional sources are
|
||||
requested subsequently. As indicated in the documentation of the [entropy module](../../sys/entropy_source/doc.txt),
|
||||
entropy is vulnerable and specific hardware sources require a priori validation.
|
||||
The `ADC noise` source requires the `periph_adc` feature of a board. Its properties can vary widely as
|
||||
depicted in the documentation of the [`ADC noise`](../../sys/include/entropy_source/adc_noise.h)
|
||||
modules and proper testing and parametrization need to take place for every single platform and ideally
|
||||
environmental properties before deployment. The test simply initializes the ADC noise entropy source
|
||||
with the default ADC pin, requests and dumps many samples with enabled health tests of the source and
|
||||
conditioning.
|
||||
|
||||
# Expected results
|
||||
The `zero entropy` is expected to indicate different errors after requesting more samples than
|
||||
the cutoff value of the Repetition Count Test (NIST SP 800-90B 4.4.1) and the Adaptive
|
||||
Proportion Test (NIST SP 800-90B 4.4.2). The expected output is:
|
||||
|
||||
## native
|
||||
|
||||
```
|
||||
# main(): This is RIOT! (Version: <version>)
|
||||
# Zero entropy single request 0/311 returned: 0
|
||||
...
|
||||
# Zero entropy single request 20/311 returned: -3
|
||||
...
|
||||
# Zero entropy single request 310/311 returned: -3
|
||||
# Zero entropy single request 311/311 returned: -5
|
||||
# Zero entropy request 64 Bytes: -5
|
||||
|
||||
```
|
||||
|
||||
## Board
|
||||
|
||||
The `ADC noise` source test should dump unpredictable values. The *von Neumann* conditioning internally
|
||||
requests multiple samples so that subsequent values include bit changes. Thus, it has
|
||||
a variable runtime. To explore this, one test requests a buffer with entropy values
|
||||
and it measures the processing time. If no changes are in place, the conditioning function
|
||||
will abort after exceeding a threshold.
|
||||
Otherwise, no health test errors should be indicated. Please note that
|
||||
missing errors do **not** reveal information about the quality of an entropy source.
|
||||
|
||||
```
|
||||
# main(): This is RIOT! (Version: <version>)
|
||||
# Zero entropy single request 0/311 returned: 0
|
||||
...
|
||||
# Zero entropy single request 20/311 returned: -3
|
||||
...
|
||||
# Zero entropy single request 311/311 returned: -5
|
||||
# Zero entropy request 64 Bytes: -5
|
||||
# ADC noise source entropy/sample: 65536 [2^16 * bit / sample]
|
||||
# ADC noise source entropy/sample: 1 [bit / sample]
|
||||
# 95
|
||||
# 9f
|
||||
# a5
|
||||
# 01
|
||||
# e1
|
||||
# 3e
|
||||
# 73
|
||||
...
|
||||
# ADC noise request 64 Bytes returned: 0. Time: <time>us
|
||||
```
|
||||
98
tests/entropy_source/main.c
Normal file
98
tests/entropy_source/main.c
Normal file
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup tests
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Test application for Entropy Sources
|
||||
*
|
||||
* @author Peter Kietzmann <peter.kietzmann@haw-hamburg.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "fmt.h"
|
||||
#include "xtimer.h"
|
||||
#include "entropy_source.h"
|
||||
#include "entropy_source/zero_entropy.h"
|
||||
#if MODULE_PERIPH_ADC
|
||||
#include "entropy_source/adc_noise.h"
|
||||
#endif
|
||||
|
||||
#ifndef NUM_BYTES
|
||||
#define NUM_BYTES (64)
|
||||
#endif
|
||||
|
||||
int main(void)
|
||||
{
|
||||
uint8_t buf1;
|
||||
uint8_t buf2[NUM_BYTES];
|
||||
int ret, prop_cutorr;
|
||||
|
||||
/* Get Adaptive Proportion Test cutoff value and use as max. number of requests */
|
||||
prop_cutorr = entropy_source_test_prop_cutoff(
|
||||
CONFIG_ENTROPY_SOURCE_ZERO_HMIN);
|
||||
|
||||
/* Initialize zero entropy source */
|
||||
entropy_source_zero_init();
|
||||
|
||||
/* Request single bytes*/
|
||||
for (int i = 0; i < prop_cutorr + 1; i++) {
|
||||
ret = entropy_source_zero_get(&buf1, 1);
|
||||
printf("Zero entropy single request %i/%i returned: %i\n", i,
|
||||
prop_cutorr, ret);
|
||||
}
|
||||
|
||||
/* Request a buffer */
|
||||
ret = entropy_source_zero_get(buf2, NUM_BYTES);
|
||||
printf("Zero entropy request %i Bytes: %i\n", NUM_BYTES, ret);
|
||||
|
||||
#if MODULE_PERIPH_ADC
|
||||
uint32_t start, stop;
|
||||
uint32_t entropy;
|
||||
|
||||
entropy = entropy_source_adc_entropy_per_sample();
|
||||
printf("ADC noise source entropy/sample: %"PRIu32" [2^16 * bit / sample]\n", \
|
||||
entropy);
|
||||
print_str("ADC noise source entropy/sample: ");
|
||||
print_float(ENTROPY_SOURCE_HMIN_SCALE_BACK(entropy), 6);
|
||||
print_str(" [bit / sample]\n");
|
||||
|
||||
/* Initialize ADC noise source */
|
||||
entropy_source_adc_init();
|
||||
|
||||
for (unsigned i = 0; i < NUM_BYTES; i++) {
|
||||
/*Request single bytes*/
|
||||
ret = entropy_source_adc_get(&buf1, 1);
|
||||
if (ret < 0) {
|
||||
printf("ADC noise single request %u/%i: %i\n", i, NUM_BYTES, ret);
|
||||
}
|
||||
else {
|
||||
printf("%02x\n", buf1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Request a buffer and measure time */
|
||||
start = xtimer_now_usec();
|
||||
ret = entropy_source_adc_get(buf2, NUM_BYTES);
|
||||
stop = xtimer_now_usec();
|
||||
|
||||
for (unsigned i = 0; i < sizeof(buf2); i++) {
|
||||
printf("%02x\n", buf2[i]);
|
||||
}
|
||||
printf("ADC noise request %i Bytes returned: %i. Time: %" PRIu32 "us\n", \
|
||||
NUM_BYTES, ret, stop - start);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user