diff --git a/Makefile.dep b/Makefile.dep index 4db804d060..d63dae9ed4 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -616,6 +616,12 @@ ifneq (,$(filter conn_can,$(USEMODULE))) USEMODULE += xtimer endif +ifneq (,$(filter puf_sram,$(USEMODULE))) + USEMODULE += hashes + USEMODULE += random + FEATURES_REQUIRED += puf_sram +endif + ifneq (,$(filter random,$(USEMODULE))) USEMODULE += prng # select default prng diff --git a/cpu/cortexm_common/ldscripts/cortexm_base.ld b/cpu/cortexm_common/ldscripts/cortexm_base.ld index 3c3389e8ad..c6413900ca 100644 --- a/cpu/cortexm_common/ldscripts/cortexm_base.ld +++ b/cpu/cortexm_common/ldscripts/cortexm_base.ld @@ -108,6 +108,7 @@ SECTIONS /* stack section */ .stack (NOLOAD): { + KEEP (*(.puf)) . = ALIGN(8); _sstack = .; KEEP (*(.isr_stack)) diff --git a/cpu/cortexm_common/vectors_cortexm.c b/cpu/cortexm_common/vectors_cortexm.c index 3cab67df2d..25b9cf18cb 100644 --- a/cpu/cortexm_common/vectors_cortexm.c +++ b/cpu/cortexm_common/vectors_cortexm.c @@ -31,6 +31,9 @@ #include "mpu.h" #include "panic.h" #include "vectors_cortexm.h" +#ifdef MODULE_PUF_SRAM +#include "puf_sram.h" +#endif #ifndef SRAM_BASE #define SRAM_BASE 0 @@ -77,6 +80,10 @@ void reset_handler_default(void) uint32_t *dst; uint32_t *src = &_etext; +#ifdef MODULE_PUF_SRAM + puf_sram_init((uint8_t *)&_srelocate, SEED_RAM_LEN); +#endif + pre_startup(); #ifdef DEVELHELP diff --git a/sys/include/puf_sram.h b/sys/include/puf_sram.h new file mode 100644 index 0000000000..74abe2576f --- /dev/null +++ b/sys/include/puf_sram.h @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2018 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_puf_sram SRAM PUF + * @ingroup sys + * + * @brief SRAM based physically unclonable function (PUF) + * @experimental + * + * @{ + * @file + * + * @author Peter Kietzmann + */ +#ifndef PUF_SRAM_H +#define PUF_SRAM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "hashes.h" +#include "thread.h" + +/** + * @brief SRAM length considered for seeding + */ +#ifndef SEED_RAM_LEN +#define SEED_RAM_LEN (2048 / sizeof(uint32_t)) +#endif + +/** + * @brief SRAM marker to detect reboot without power-off + * + * Source: https://www.random.org/bytes/ + */ +#define PUF_SRAM_MARKER (0xad3021ff) + +/** + * @brief Global seed variable, allocated in puf_sram.c + */ +extern uint32_t puf_sram_seed; + +/** + * @brief Global seed state, allocated in puf_sram.c + * 0 means seed was generated from SRAM pattern, + 1 means missing power cycle detected, + 2 means power cycle detected. The state will most likely + be overwritten with 0 in the next steps + */ +extern uint32_t puf_sram_state; + +/** + * @brief checks source of reboot by @p puf_sram_softreset and conditionally + calls @p puf_sram_generate + * + * @param[in] ram pointer to SRAM memory + * @param[in] len length of the memroy to consider + * + */ +void puf_sram_init(const uint8_t *ram, size_t len); + +/** + * @brief builds hash from @p SEED_RAM_LEN bytes uninitialized SRAM, writes it + * to the global variable @p puf_sram_seed and returns the value + * + * @param[in] ram pointer to SRAM memory + * @param[in] len length of the memroy to consider + */ +void puf_sram_generate(const uint8_t *ram, size_t len); + +/** + * @brief checks for a memory marker to determine whether memory contains old data. + Otherwise it assumes a reboot from power down mode + * + * @return 0 when reset with power cycle was detected + * @return 1 when reset without power cycle was detected + */ +bool puf_sram_softreset(void); + + +#ifdef __cplusplus +} +#endif +/** @} */ +#endif /* PUF_SRAM_H */ diff --git a/sys/puf_sram/Makefile b/sys/puf_sram/Makefile new file mode 100644 index 0000000000..1d822bf823 --- /dev/null +++ b/sys/puf_sram/Makefile @@ -0,0 +1,3 @@ +$(warning Attention! Module PUF SRAM requires power-off in order to generate a\ + high-entropy seed) +include $(RIOTBASE)/Makefile.base diff --git a/sys/puf_sram/puf_sram.c b/sys/puf_sram/puf_sram.c new file mode 100644 index 0000000000..2617b2e43f --- /dev/null +++ b/sys/puf_sram/puf_sram.c @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2018 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_puf_sram + * + * @{ + * @file + * + * @author Peter Kietzmann + * + * @} + */ +#include "puf_sram.h" + +/* Allocation of the PUF seed variable */ +__attribute__((used,section(".puf"))) uint32_t puf_sram_seed; + +/* Allocation of the PUF seed state */ +__attribute__((used,section(".puf"))) uint32_t puf_sram_state; + +/* Allocation of the memory marker */ +__attribute__((used,section(".puf"))) uint32_t puf_sram_marker; + +void puf_sram_init(const uint8_t *ram, size_t len) +{ + /* generates a new seed value if power cycle was detected */ + if (!puf_sram_softreset()) { + puf_sram_generate(ram, len); + } +} +void puf_sram_generate(const uint8_t *ram, size_t len) +{ + /* build hash from start-up pattern */ + puf_sram_seed = dek_hash(ram, len); + /* write marker to a defined section for subsequent reset detection */ + puf_sram_marker = PUF_SRAM_MARKER; + /* seting state to 0 means seed was generated from SRAM pattern */ + puf_sram_state = 0; +} + +bool puf_sram_softreset(void) +{ + if (puf_sram_marker != PUF_SRAM_MARKER) { + puf_sram_state = 2; + return 0; + } + puf_sram_state = 1; + return 1; +} diff --git a/sys/random/random.c b/sys/random/random.c index ad80880167..8449507b3f 100644 --- a/sys/random/random.c +++ b/sys/random/random.c @@ -23,6 +23,9 @@ #include "luid.h" #include "periph/cpuid.h" #include "random.h" +#ifdef MODULE_PUF_SRAM +#include "puf_sram.h" +#endif #define ENABLE_DEBUG (0) #include "debug.h" @@ -30,7 +33,13 @@ void auto_init_random(void) { uint32_t seed; -#ifdef MODULE_PERIPH_CPUID +#ifdef MODULE_PUF_SRAM + /* TODO: hand state to application? */ + if (puf_sram_state) { + LOG_WARNING("random: PUF SEED not fresh\n"); + } + seed = puf_sram_seed; +#elif defined (MODULE_PERIPH_CPUID) luid_get(&seed, 4); #else LOG_WARNING("random: NO SEED AVAILABLE!\n");