Skip to content

Commit 20efcde

Browse files
committed
Implement a fast PRNG based on ascon
Fix a bunch of bias related bugs in the process
1 parent c7c400e commit 20efcde

30 files changed

Lines changed: 1030 additions & 57 deletions

examples/companion_radio/MyMesh.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -882,10 +882,10 @@ void MyMesh::begin(bool has_display) {
882882
BaseChatMesh::begin();
883883

884884
if (!_store->loadMainIdentity(self_id)) {
885-
self_id = radio_new_identity(); // create new random identity
885+
self_id = mesh::LocalIdentity(getRNG()); // create new random identity
886886
int count = 0;
887887
while (count < 10 && (self_id.pub_key[0] == 0x00 || self_id.pub_key[0] == 0xFF)) { // reserved id hashes
888-
self_id = radio_new_identity();
888+
self_id = mesh::LocalIdentity(getRNG());
889889
count++;
890890
}
891891
_store->saveMainIdentity(self_id);
@@ -930,8 +930,7 @@ void MyMesh::begin(bool has_display) {
930930
if (_prefs.ble_pin == 0) {
931931
#ifdef DISPLAY_CLASS
932932
if (has_display && BLE_PIN_CODE == 123456) {
933-
StdRNG rng;
934-
_active_ble_pin = rng.nextInt(100000, 999999); // random pin each session
933+
_active_ble_pin = getRNG()->nextInt(100000, 999999); // random pin each session
935934
} else {
936935
_active_ble_pin = BLE_PIN_CODE; // otherwise static pin
937936
}

examples/companion_radio/main.cpp

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ void setup() {
109109
Serial.begin(115200);
110110

111111
board.begin();
112+
mesh::initHardwareRNG();
112113

113114
#ifdef DISPLAY_CLASS
114115
DisplayDriver* disp = NULL;
@@ -123,12 +124,13 @@ void setup() {
123124
}
124125
#endif
125126

126-
if (!radio_init()) { halt(); }
127-
128-
fast_rng.begin(radio_get_rng_seed());
129-
130127
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
131128
InternalFS.begin();
129+
fast_rng.attachPersistence(InternalFS, "/seed.rng");
130+
fast_rng.setRadioEntropySource(radio_driver);
131+
fast_rng.begin();
132+
mesh::deinitHardwareRNG();
133+
if (!radio_init()) { halt(); }
132134
#if defined(QSPIFLASH)
133135
if (!QSPIFlash.begin()) {
134136
// debug output might not be available at this point, might be too early. maybe should fall back to InternalFS here?
@@ -158,6 +160,11 @@ void setup() {
158160
the_mesh.startInterface(serial_interface);
159161
#elif defined(RP2040_PLATFORM)
160162
LittleFS.begin();
163+
fast_rng.attachPersistence(LittleFS, "/seed.rng");
164+
fast_rng.setRadioEntropySource(radio_driver);
165+
fast_rng.begin();
166+
mesh::deinitHardwareRNG();
167+
if (!radio_init()) { halt(); }
161168
store.begin();
162169
the_mesh.begin(
163170
#ifdef DISPLAY_CLASS
@@ -184,6 +191,11 @@ void setup() {
184191
the_mesh.startInterface(serial_interface);
185192
#elif defined(ESP32)
186193
SPIFFS.begin(true);
194+
fast_rng.attachPersistence(SPIFFS, "/seed.rng");
195+
fast_rng.setRadioEntropySource(radio_driver);
196+
fast_rng.begin();
197+
mesh::deinitHardwareRNG();
198+
if (!radio_init()) { halt(); }
187199
store.begin();
188200
the_mesh.begin(
189201
#ifdef DISPLAY_CLASS

examples/kiss_modem/main.cpp

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,24 +32,29 @@ void halt() {
3232
}
3333

3434
void loadOrCreateIdentity() {
35+
FILESYSTEM* fs;
3536
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
3637
InternalFS.begin();
38+
fs = &InternalFS;
3739
IdentityStore store(InternalFS, "");
3840
#elif defined(ESP32)
3941
SPIFFS.begin(true);
42+
fs = &SPIFFS;
4043
IdentityStore store(SPIFFS, "/identity");
4144
#elif defined(RP2040_PLATFORM)
4245
LittleFS.begin();
46+
fs = &LittleFS;
4347
IdentityStore store(LittleFS, "/identity");
4448
store.begin();
4549
#else
4650
#error "Filesystem not defined"
4751
#endif
52+
rng.attachPersistence(*fs, "/seed.rng");
4853

4954
if (!store.load("_main", identity)) {
50-
identity = radio_new_identity();
55+
identity = mesh::LocalIdentity(&rng);
5156
while (identity.pub_key[0] == 0x00 || identity.pub_key[0] == 0xFF) {
52-
identity = radio_new_identity();
57+
identity = mesh::LocalIdentity(&rng);
5358
}
5459
store.save("_main", identity);
5560
}
@@ -75,16 +80,19 @@ void onGetStats(uint32_t* rx, uint32_t* tx, uint32_t* errors) {
7580

7681
void setup() {
7782
board.begin();
83+
mesh::initHardwareRNG();
84+
85+
loadOrCreateIdentity();
86+
rng.setRadioEntropySource(radio_driver);
87+
rng.begin();
88+
mesh::deinitHardwareRNG();
7889

7990
if (!radio_init()) {
8091
halt();
8192
}
8293

8394
radio_driver.begin();
8495

85-
rng.begin(radio_get_rng_seed());
86-
loadOrCreateIdentity();
87-
8896
sensors.begin();
8997

9098
#if defined(KISS_UART_RX) && defined(KISS_UART_TX)

examples/simple_repeater/main.cpp

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ void setup() {
3333
delay(1000);
3434

3535
board.begin();
36+
mesh::initHardwareRNG();
3637

3738
#if defined(MESH_DEBUG) && defined(NRF52_PLATFORM)
3839
// give some extra time for serial to settle so
@@ -52,13 +53,6 @@ void setup() {
5253
}
5354
#endif
5455

55-
if (!radio_init()) {
56-
MESH_DEBUG_PRINTLN("Radio init failed!");
57-
halt();
58-
}
59-
60-
fast_rng.begin(radio_get_rng_seed());
61-
6256
FILESYSTEM* fs;
6357
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
6458
InternalFS.begin();
@@ -76,12 +70,22 @@ void setup() {
7670
#else
7771
#error "need to define filesystem"
7872
#endif
73+
fast_rng.attachPersistence(*fs, "/seed.rng");
74+
fast_rng.setRadioEntropySource(radio_driver);
75+
fast_rng.begin();
76+
mesh::deinitHardwareRNG();
77+
78+
if (!radio_init()) {
79+
MESH_DEBUG_PRINTLN("Radio init failed!");
80+
halt();
81+
}
82+
7983
if (!store.load("_main", the_mesh.self_id)) {
8084
MESH_DEBUG_PRINTLN("Generating new keypair");
81-
the_mesh.self_id = radio_new_identity(); // create new random identity
85+
the_mesh.self_id = mesh::LocalIdentity(the_mesh.getRNG()); // create new random identity
8286
int count = 0;
8387
while (count < 10 && (the_mesh.self_id.pub_key[0] == 0x00 || the_mesh.self_id.pub_key[0] == 0xFF)) { // reserved id hashes
84-
the_mesh.self_id = radio_new_identity(); count++;
88+
the_mesh.self_id = mesh::LocalIdentity(the_mesh.getRNG()); count++;
8589
}
8690
store.save("_main", the_mesh.self_id);
8791
}

examples/simple_room_server/main.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ void setup() {
2323
delay(1000);
2424

2525
board.begin();
26+
mesh::initHardwareRNG();
2627

2728
#ifdef DISPLAY_CLASS
2829
if (display.begin()) {
@@ -33,10 +34,6 @@ void setup() {
3334
}
3435
#endif
3536

36-
if (!radio_init()) { halt(); }
37-
38-
fast_rng.begin(radio_get_rng_seed());
39-
4037
FILESYSTEM* fs;
4138
#if defined(NRF52_PLATFORM)
4239
InternalFS.begin();
@@ -54,11 +51,18 @@ void setup() {
5451
#else
5552
#error "need to define filesystem"
5653
#endif
54+
fast_rng.attachPersistence(*fs, "/seed.rng");
55+
fast_rng.setRadioEntropySource(radio_driver);
56+
fast_rng.begin();
57+
mesh::deinitHardwareRNG();
58+
59+
if (!radio_init()) { halt(); }
60+
5761
if (!store.load("_main", the_mesh.self_id)) {
58-
the_mesh.self_id = radio_new_identity(); // create new random identity
62+
the_mesh.self_id = mesh::LocalIdentity(the_mesh.getRNG()); // create new random identity
5963
int count = 0;
6064
while (count < 10 && (the_mesh.self_id.pub_key[0] == 0x00 || the_mesh.self_id.pub_key[0] == 0xFF)) { // reserved id hashes
61-
the_mesh.self_id = radio_new_identity(); count++;
65+
the_mesh.self_id = mesh::LocalIdentity(the_mesh.getRNG()); count++;
6266
}
6367
store.save("_main", the_mesh.self_id);
6468
}

examples/simple_secure_chat/main.cpp

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -307,14 +307,6 @@ class MyMesh : public BaseChatMesh, ContactVisitor {
307307
IdentityStore store(fs, "/identity");
308308
#endif
309309
if (!store.load("_main", self_id, _prefs.node_name, sizeof(_prefs.node_name))) { // legacy: node_name was from identity file
310-
// Need way to get some entropy to seed RNG
311-
Serial.println("Press ENTER to generate key:");
312-
char c = 0;
313-
while (c != '\n') { // wait for ENTER to be pressed
314-
if (Serial.available()) c = Serial.read();
315-
}
316-
((StdRNG *)getRNG())->begin(millis());
317-
318310
self_id = mesh::LocalIdentity(getRNG()); // create new random identity
319311
int count = 0;
320312
while (count < 10 && (self_id.pub_key[0] == 0x00 || self_id.pub_key[0] == 0xFF)) { // reserved id hashes
@@ -559,23 +551,32 @@ void setup() {
559551
Serial.begin(115200);
560552

561553
board.begin();
554+
mesh::initHardwareRNG();
562555

563-
if (!radio_init()) { halt(); }
564-
565-
fast_rng.begin(radio_get_rng_seed());
556+
FILESYSTEM* fs;
566557

567558
#if defined(NRF52_PLATFORM)
568559
InternalFS.begin();
569-
the_mesh.begin(InternalFS);
560+
fs = &InternalFS;
561+
fast_rng.attachPersistence(InternalFS, "/seed.rng");
570562
#elif defined(RP2040_PLATFORM)
571563
LittleFS.begin();
572-
the_mesh.begin(LittleFS);
564+
fs = &LittleFS;
565+
fast_rng.attachPersistence(LittleFS, "/seed.rng");
573566
#elif defined(ESP32)
574567
SPIFFS.begin(true);
575-
the_mesh.begin(SPIFFS);
568+
fs = &SPIFFS;
569+
fast_rng.attachPersistence(SPIFFS, "/seed.rng");
576570
#else
577571
#error "need to define filesystem"
578572
#endif
573+
fast_rng.setRadioEntropySource(radio_driver);
574+
fast_rng.begin();
575+
mesh::deinitHardwareRNG();
576+
577+
if (!radio_init()) { halt(); }
578+
579+
the_mesh.begin(*fs);
579580

580581
radio_set_params(the_mesh.getFreqPref(), LORA_BW, LORA_SF, LORA_CR);
581582
radio_set_tx_power(the_mesh.getTxPowerPref());

examples/simple_sensor/main.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ void setup() {
5757
delay(1000);
5858

5959
board.begin();
60+
mesh::initHardwareRNG();
6061

6162
#ifdef DISPLAY_CLASS
6263
if (display.begin()) {
@@ -66,10 +67,6 @@ void setup() {
6667
}
6768
#endif
6869

69-
if (!radio_init()) { halt(); }
70-
71-
fast_rng.begin(radio_get_rng_seed());
72-
7370
FILESYSTEM* fs;
7471
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
7572
InternalFS.begin();
@@ -87,12 +84,19 @@ void setup() {
8784
#else
8885
#error "need to define filesystem"
8986
#endif
87+
fast_rng.attachPersistence(*fs, "/seed.rng");
88+
fast_rng.setRadioEntropySource(radio_driver);
89+
fast_rng.begin();
90+
mesh::deinitHardwareRNG();
91+
92+
if (!radio_init()) { halt(); }
93+
9094
if (!store.load("_main", the_mesh.self_id)) {
9195
MESH_DEBUG_PRINTLN("Generating new keypair");
92-
the_mesh.self_id = radio_new_identity(); // create new random identity
96+
the_mesh.self_id = mesh::LocalIdentity(the_mesh.getRNG()); // create new random identity
9397
int count = 0;
9498
while (count < 10 && (the_mesh.self_id.pub_key[0] == 0x00 || the_mesh.self_id.pub_key[0] == 0xFF)) { // reserved id hashes
95-
the_mesh.self_id = radio_new_identity(); count++;
99+
the_mesh.self_id = mesh::LocalIdentity(the_mesh.getRNG()); count++;
96100
}
97101
store.save("_main", the_mesh.self_id);
98102
}

lib/ascon/api.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#define CRYPTO_VERSION "1.3.0"
2+
#define CRYPTO_BYTES 64
3+
#define ASCON_HASH_BYTES 0 /* XOF */
4+
#define ASCON_HASH_ROUNDS 12
5+
#define ASCON_VARIANT 3

lib/ascon/ascon.h

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#ifndef ASCON_H_
2+
#define ASCON_H_
3+
4+
#include <stdint.h>
5+
6+
#include "api.h"
7+
#include "config.h"
8+
9+
#ifdef __cplusplus
10+
extern "C" {
11+
#endif
12+
13+
typedef union {
14+
uint64_t x[5];
15+
uint32_t w[5][2];
16+
uint8_t b[5][8];
17+
} ascon_state_t;
18+
19+
#ifdef ASCON_AEAD_RATE
20+
21+
#define ASCON_KEYWORDS (CRYPTO_KEYBYTES + 7) / 8
22+
23+
typedef union {
24+
uint64_t x[ASCON_KEYWORDS];
25+
uint32_t w[ASCON_KEYWORDS][2];
26+
uint8_t b[ASCON_KEYWORDS][8];
27+
} ascon_key_t;
28+
29+
#if !ASCON_INLINE_MODE
30+
31+
void ascon_loadkey(ascon_key_t* key, const uint8_t* k);
32+
void ascon_initaead(ascon_state_t* s, const ascon_key_t* key,
33+
const uint8_t* npub);
34+
void ascon_adata(ascon_state_t* s, const uint8_t* ad, uint64_t adlen);
35+
void ascon_encrypt(ascon_state_t* s, uint8_t* c, const uint8_t* m,
36+
uint64_t mlen);
37+
void ascon_decrypt(ascon_state_t* s, uint8_t* m, const uint8_t* c,
38+
uint64_t clen);
39+
void ascon_final(ascon_state_t* s, const ascon_key_t* k);
40+
41+
#endif
42+
43+
int ascon_aead_encrypt(uint8_t* t, uint8_t* c, const uint8_t* m, uint64_t mlen,
44+
const uint8_t* ad, uint64_t adlen, const uint8_t* npub,
45+
const uint8_t* k);
46+
int ascon_aead_decrypt(uint8_t* m, const uint8_t* t, const uint8_t* c,
47+
uint64_t clen, const uint8_t* ad, uint64_t adlen,
48+
const uint8_t* npub, const uint8_t* k);
49+
50+
#endif
51+
52+
#ifdef ASCON_HASH_BYTES
53+
54+
#if !ASCON_INLINE_MODE
55+
56+
void ascon_inithash(ascon_state_t* s);
57+
void ascon_absorb(ascon_state_t* s, const uint8_t* in, uint64_t inlen);
58+
void ascon_squeeze(ascon_state_t* s, uint8_t* out, uint64_t outlen);
59+
60+
#endif
61+
62+
int ascon_xof(uint8_t* out, uint64_t outlen, const uint8_t* in, uint64_t inlen);
63+
64+
#endif
65+
66+
#ifdef __cplusplus
67+
}
68+
#endif
69+
70+
#endif /* ASCON_H_ */

0 commit comments

Comments
 (0)