diff --git a/core/MySigningAtsha204Soft.cpp b/core/MySigningAtsha204Soft.cpp
index dc9645a..2a4d064 100644
--- a/core/MySigningAtsha204Soft.cpp
+++ b/core/MySigningAtsha204Soft.cpp
@@ -109,6 +109,10 @@ bool signerAtsha204SoftGetNonce(MyMessage &msg)
}
SIGN_DEBUG(PSTR("Signing backend: ATSHA204Soft\n"));
+#ifdef MY_HW_HAS_GETRANDOM
+ // Try to get MAX_PAYLOAD random bytes
+ while (hwGetentropy(&_signing_verifying_nonce, MAX_PAYLOAD) != MAX_PAYLOAD);
+#else
// We used a basic whitening technique that XORs a random byte with the current hwMillis() counter and then the byte is
// hashed (SHA256) to produce the resulting nonce
_signing_sha256.init();
@@ -116,6 +120,7 @@ bool signerAtsha204SoftGetNonce(MyMessage &msg)
_signing_sha256.write(random(256) ^ (hwMillis()&0xFF));
}
memcpy(_signing_verifying_nonce, _signing_sha256.result(), MAX_PAYLOAD);
+#endif
// We set the part of the 32-byte nonce that does not fit into a message to 0xAA
memset(&_signing_verifying_nonce[MAX_PAYLOAD], 0xAA, sizeof(_signing_verifying_nonce)-MAX_PAYLOAD);
diff --git a/examples/SecurityPersonalizer/SecurityPersonalizer.ino b/examples/SecurityPersonalizer/SecurityPersonalizer.ino
index 3d9d2fb..acc47c8 100644
--- a/examples/SecurityPersonalizer/SecurityPersonalizer.ino
+++ b/examples/SecurityPersonalizer/SecurityPersonalizer.ino
@@ -72,7 +72,7 @@
*
* @b Important
* You will need to ensure @ref MY_SIGNING_SOFT_RANDOMSEED_PIN is set to an unconnected analog pin
- * in order to provide entropy to the software RNG.
+ * in order to provide entropy to the software RNG if your hardware has no HWRNG.
*
* @note The generated keys displayed in the serial log with this setting needs to be written down
* and transferred to all nodes this gateway will communicate with. This is mandatory for ALL
@@ -436,7 +436,7 @@ void setup()
while (hwMillis() - enter < (unsigned long)500);
#ifdef USE_SOFT_SIGNING
// initialize pseudo-RNG
- randomSeed(analogRead(MY_SIGNING_SOFT_RANDOMSEED_PIN));
+ hwRandomNumberInit();
#endif
Serial.begin(MY_BAUD_RATE);
diff --git a/hal/architecture/MyHw.h b/hal/architecture/MyHw.h
index 91bcaf6..fd78f47 100644
--- a/hal/architecture/MyHw.h
+++ b/hal/architecture/MyHw.h
@@ -43,6 +43,14 @@ void hwWriteConfig(int adr, uint8_t value);
uint8_t hwReadConfig(int adr);
*/
+/**
+ * @def MY_HW_HAS_GETRANDOM
+ * @brief Define this, if hwGetentropy is implemented
+ *
+ * ssize_t hwGetentropy(void *__buffer, size_t __length);
+ */
+//#define MY_HW_HAS_GETRANDOM
+
/**
* Sleep for a defined time, using minimum power.
* @param ms Time to sleep, in [ms].
@@ -138,6 +146,7 @@ void hwDebugPrint(const char *fmt, ... );
*/
#ifdef DOXYGEN
#define MY_CRITICAL_SECTION
+#define MY_HW_HAS_GETRANDOM
#endif /* DOXYGEN */
#endif // #ifdef MyHw_h
diff --git a/hal/architecture/MyHwAVR.cpp b/hal/architecture/MyHwAVR.cpp
index 5079a71..adef13c 100644
--- a/hal/architecture/MyHwAVR.cpp
+++ b/hal/architecture/MyHwAVR.cpp
@@ -202,6 +202,41 @@ int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mo
return ret;
}
+inline void hwRandomNumberInit()
+{
+ // This function initializes the random number generator with a seed
+ // of 32 bits. This method is good enough to earn FIPS 140-2 conform
+ // random data. This should reach to generate 32 Bit for randomSeed().
+ unsigned long seed = 0;
+ unsigned long start = millis();
+ unsigned long timeout = start + 20;
+
+ // Trigger floating effect of an unconnected pin
+ pinMode(MY_SIGNING_SOFT_RANDOMSEED_PIN, INPUT_PULLUP);
+ pinMode(MY_SIGNING_SOFT_RANDOMSEED_PIN, INPUT);
+ delay(10);
+
+ // Generate 32 bits of datas
+ for (uint8_t i=0; i<32; i++) {
+ int pinValue = analogRead(MY_SIGNING_SOFT_RANDOMSEED_PIN);
+ // Wait until the analog value has changed
+ while ((pinValue == analogRead(MY_SIGNING_SOFT_RANDOMSEED_PIN)) && (timeout>=millis())) {
+ seed ^= (millis() << i);
+ // Check of data generation is slow
+ if (timeout<=millis()) {
+ // Trigger pin again
+ pinMode(MY_SIGNING_SOFT_RANDOMSEED_PIN, INPUT_PULLUP);
+ pinMode(MY_SIGNING_SOFT_RANDOMSEED_PIN, INPUT);
+ // Pause a short while
+ delay(seed % 10);
+ timeout = millis()+20;
+ }
+ }
+ }
+
+ randomSeed(seed);
+}
+
bool hwUniqueID(unique_id_t* uniqueID)
{
// not implemented yet
diff --git a/hal/architecture/MyHwAVR.h b/hal/architecture/MyHwAVR.h
index 183db74..7eb640d 100644
--- a/hal/architecture/MyHwAVR.h
+++ b/hal/architecture/MyHwAVR.h
@@ -48,12 +48,12 @@ bool hwInit(void);
#define hwWatchdogReset() wdt_reset()
#define hwReboot() wdt_enable(WDTO_15MS); while (1)
#define hwMillis() millis()
-#define hwRandomNumberInit() randomSeed(analogRead(MY_SIGNING_SOFT_RANDOMSEED_PIN))
#define hwReadConfig(__pos) eeprom_read_byte((uint8_t*)(__pos))
#define hwWriteConfig(__pos, __val) eeprom_update_byte((uint8_t*)(__pos), (__val))
#define hwReadConfigBlock(__buf, __pos, __length) eeprom_read_block((void*)(__buf), (void*)(__pos), (__length))
#define hwWriteConfigBlock(__buf, __pos, __length) eeprom_update_block((void*)(__buf), (void*)(__pos), (__length))
+inline void hwRandomNumberInit();
void hwInternalSleep(unsigned long ms);
#ifndef DOXYGEN
diff --git a/hal/architecture/MyHwESP8266.cpp b/hal/architecture/MyHwESP8266.cpp
index 6913344..b2f053a 100644
--- a/hal/architecture/MyHwESP8266.cpp
+++ b/hal/architecture/MyHwESP8266.cpp
@@ -73,6 +73,21 @@ bool hwUniqueID(unique_id_t *uniqueID)
return true;
}
+ssize_t hwGetentropy(void *__buffer, size_t __length)
+{
+ // cut length if > 256
+ if (__length > 256) {
+ __length = 256;
+ }
+ uint8_t *dst = (uint8_t *)__buffer;
+
+ // Start random number generator
+ for (size_t i = 0; i < __length; i++) {
+ dst[i] = (uint8_t)RANDOM_REG32;
+ }
+
+ return __length;
+}
int8_t hwSleep(unsigned long ms)
{
diff --git a/hal/architecture/MyHwESP8266.h b/hal/architecture/MyHwESP8266.h
index a713bba..2550f7a 100644
--- a/hal/architecture/MyHwESP8266.h
+++ b/hal/architecture/MyHwESP8266.h
@@ -41,13 +41,16 @@
#define hwWatchdogReset() wdt_reset()
#define hwReboot() ESP.restart()
#define hwMillis() millis()
-#define hwRandomNumberInit() randomSeed(RANDOM_REG32)
+// The use of randomSeed switch to pseudo random number. Keep hwRandomNumberInit empty
+#define hwRandomNumberInit()
bool hwInit(void);
void hwReadConfigBlock(void* buf, void* adr, size_t length);
void hwWriteConfigBlock(void* buf, void* adr, size_t length);
void hwWriteConfig(const int addr, uint8_t value);
uint8_t hwReadConfig(const int addr);
+ssize_t hwGetentropy(void *__buffer, size_t __length);
+//#define MY_HW_HAS_GETRANDOM
/**
* Restore interrupt state.
diff --git a/hal/architecture/MyHwLinuxGeneric.cpp b/hal/architecture/MyHwLinuxGeneric.cpp
index 09c1dbe..3c8070d 100644
--- a/hal/architecture/MyHwLinuxGeneric.cpp
+++ b/hal/architecture/MyHwLinuxGeneric.cpp
@@ -19,7 +19,13 @@
#include "MyHwLinuxGeneric.h"
+#include
+#include
#include
+#include
+#include
+#include
+#include
#include
#include "SoftEeprom.h"
#include "log.h"
@@ -62,7 +68,15 @@ void hwWriteConfig(int addr, uint8_t value)
void hwRandomNumberInit()
{
- randomSeed(time(NULL));
+ unsigned long seed=0;
+ while (hwGetentropy(&seed, sizeof(seed)) != sizeof(seed));
+ randomSeed(seed);
+}
+
+ssize_t hwGetentropy(void *__buffer, size_t __length)
+{
+ // getrandom syscall
+ return syscall(SYS_getrandom, __buffer, __length, GRND_NONBLOCK);
}
unsigned long hwMillis()
diff --git a/hal/architecture/MyHwLinuxGeneric.h b/hal/architecture/MyHwLinuxGeneric.h
index 5074ae8..ce89572 100644
--- a/hal/architecture/MyHwLinuxGeneric.h
+++ b/hal/architecture/MyHwLinuxGeneric.h
@@ -54,6 +54,8 @@ inline void hwWriteConfigBlock(void* buf, void* addr, size_t length);
inline uint8_t hwReadConfig(int addr);
inline void hwWriteConfig(int addr, uint8_t value);
inline void hwRandomNumberInit();
+ssize_t hwGetentropy(void *__buffer, size_t __length);
+#define MY_HW_HAS_GETRANDOM
inline unsigned long hwMillis();
#ifdef MY_RF24_IRQ_PIN
diff --git a/hal/architecture/MyHwNRF5.cpp b/hal/architecture/MyHwNRF5.cpp
index 18893be..889343e 100644
--- a/hal/architecture/MyHwNRF5.cpp
+++ b/hal/architecture/MyHwNRF5.cpp
@@ -84,6 +84,9 @@ bool hwInit()
return true;
}
+static nrf_ecb_t hwRngData;
+static int8_t hwRndDataReadPos = -1;
+
void hwRandomNumberInit()
{
// Start HWRNG
@@ -106,6 +109,17 @@ void hwRandomNumberInit()
}
randomSeed(seed);
+ // Fill ESB data structure for fast random data generation
+ uint8_t *ecbstruct = (uint8_t *)&hwRngData;
+ for (uint8_t i = 0; iEVENTS_VALRDY == 0) {
+ yield();
+ }
+ ecbstruct[i] = NRF_RNG->VALUE;
+ NRF_RNG->EVENTS_VALRDY = 0;
+ }
+ hwRndDataReadPos = 0;
+
// Stop HWRNG
NRF_RNG->TASKS_STOP = 1;
#ifdef NRF51
@@ -113,6 +127,55 @@ void hwRandomNumberInit()
#endif
}
+ssize_t hwGetentropy(void *__buffer, size_t __length)
+{
+ if (hwRndDataReadPos<0) {
+ // Not initialized
+ hwRandomNumberInit();
+ }
+
+ // cut length if > 256
+ if (__length > 256) {
+ __length = 256;
+ }
+ uint8_t *dst = (uint8_t *)__buffer;
+
+ // Start random number generator
+ for (size_t i = 0; i < __length; i++) {
+ dst[i] = hwRngData.ciphertext[hwRndDataReadPos & 0xfu];
+ MY_CRITICAL_SECTION {
+ if (hwRndDataReadPos >= ((int8_t)sizeof(hwRngData.ciphertext)-1))
+ {
+ // Retry until no error
+ bool need_data = true;
+ while (need_data) {
+ // Stop if another task is running
+ NRF_ECB->TASKS_STOPECB = 1;
+ NRF_ECB->EVENTS_ERRORECB = 0;
+ NRF_ECB->EVENTS_ENDECB = 0;
+ uint32_t ptrbackup = NRF_ECB->ECBDATAPTR;
+ NRF_ECB->ECBDATAPTR = (uint32_t)&hwRngData;
+ NRF_ECB->TASKS_STARTECB = 1;
+ while (!NRF_ECB->EVENTS_ENDECB);
+ NRF_ECB->ECBDATAPTR = ptrbackup;
+ if (NRF_ECB->EVENTS_ERRORECB == 0) {
+ need_data = false;
+ }
+ }
+ hwRndDataReadPos=0;
+ for (uint8_t i=0; iRR[0] = WDT_RR_RR_Reload;
diff --git a/hal/architecture/MyHwNRF5.h b/hal/architecture/MyHwNRF5.h
index a5dbb06..2ebba32 100644
--- a/hal/architecture/MyHwNRF5.h
+++ b/hal/architecture/MyHwNRF5.h
@@ -59,6 +59,8 @@ void hwWriteConfigBlock(void *buf, void *adr, size_t length);
void hwWriteConfig(int adr, uint8_t value);
uint8_t hwReadConfig(int adr);
void hwRandomNumberInit();
+ssize_t hwGetentropy(void *__buffer, size_t __length);
+#define MY_HW_HAS_GETRANDOM
#ifndef MY_SERIALDEVICE
#define MY_SERIALDEVICE Serial
@@ -110,6 +112,20 @@ static __inline__ void __priMaskRestore(const uint32_t *priMask)
#define MY_HW_RTC_IRQN RTC0_IRQn
#endif
+/** Datastructure for AES ECB unit
+ */
+typedef struct {
+ /** AES Key
+ */
+ uint8_t key[16];
+ /** Unencrypted data
+ */
+ uint8_t cleartext[16];
+ /** Encrypted data
+ */
+ uint8_t ciphertext[16];
+} nrf_ecb_t;
+
#ifndef DOXYGEN
#define MY_CRITICAL_SECTION
// temp. commented, to fix "CircularBuffer.h:94:2: warning: control reaches end of non-void function" error