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 "color/Kconfig"
|
||||||
rsource "div/Kconfig"
|
rsource "div/Kconfig"
|
||||||
rsource "embunit/Kconfig"
|
rsource "embunit/Kconfig"
|
||||||
|
rsource "entropy_source/Kconfig"
|
||||||
rsource "event/Kconfig"
|
rsource "event/Kconfig"
|
||||||
rsource "fmt/Kconfig"
|
rsource "fmt/Kconfig"
|
||||||
rsource "isrpipe/Kconfig"
|
rsource "isrpipe/Kconfig"
|
||||||
|
|||||||
@ -706,6 +706,13 @@ ifneq (,$(filter conn_can,$(USEMODULE)))
|
|||||||
USEMODULE += xtimer
|
USEMODULE += xtimer
|
||||||
endif
|
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)))
|
ifneq (,$(filter puf_sram,$(USEMODULE)))
|
||||||
USEMODULE += hashes
|
USEMODULE += hashes
|
||||||
USEMODULE += random
|
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