After soaking for a bit on the adverts without issue on multiple nodes,
I added more hardware crypto.
Supported nodes is unchanged in this PR addition, but if others can verify,
they can easily be added.
Some info on the CC310: https://docs.nordicsemi.com/r/bundle/ps_nrf9151/page/cryptocell.html
**Added:**
- AES-128 packet encryption/decryption now use hardware crypto
- HMAC-SHA-256 authentication now uses hardware crypto
- ACK hash computation and channel ID derivation now use hardware crypto
- RNG (random number generator) now uses hardware crypto rather than
radio noise + weak software RNG (which can have issues if there's
no surrounding radio noise.) NIST SP 800-90B certified.
- Runs hardware self-tests on startup
- Runs continuous health tests during operation
- Uses thermal noise/shot noise for randomness
**Unchanged:**
- calcSharedSecret remains software - it would be a split hw/sw solution
and added complexity for likely not a lot of gains. This only happens
when establishing a new contact, so not too frequent to be worth it.
- ed25519_create_keypair remains software. This is only called when a
node is first initialized. It does use the hardware RNG change, however,
so better randomization.
Tested on (so far):
- Heltec t096
Build test on:
- Heltec t096 companion ble
- t1000e companion ble
- RAK 4631 repeater
- RAK 3401 companion BLE
- Heltec v3 companion wifi
next_check and next_gps_update stored a future millis() value in a signed
long and compared with a naive '>'. After the ~24.8-day millis() sign flip
the deadline sits above the wrapped millis(), so the block never runs again
and GPS->RTC time-sync (and the location cache refresh) stall permanently
until reboot. Switch to unsigned deadlines with the wrap-safe signed-
difference compare '(long)(millis() - deadline) > 0', matching the idiom in
Dispatcher::millisHasNowPassed.
Also: reorder the MicroNMEALocationProvider ctor init-list to declaration
order (silences -Wreorder) and drop the always-true 'if (_claims > 0)' guard
in claim() (claim() always runs after _claims++, so it is >= 1).
Previously load() returned true unconditionally on file-open success,
masking truncated or corrupt /regions2 files. Additionally, the first
field of each entry record (r->id) used the same success-chaining
pattern as subsequent fields, so a clean EOF at a record boundary set
success=false and would have been indistinguishable from real
corruption once the return value was fixed.
The r->id read is now split out: n==0 is a clean EOF (break, success
retains its prior value from the header read), n!=sizeof(r->id) is a
partial read or corruption (break, success=false). load() now returns
success instead of an unconditional true, so its return value reflects
the actual parse outcome.
Companion fix to #2372, which fixed the same return-true hardcoding
in save(). (#1891 originally reported this on load() but was closed
when #2372 landed — that PR only touched save(); this addresses the
load() side.)
GPS support was implemented incorrectly for the ThinkNode M3. The reset
pin was being driven when it should be left floating for this unit. The
enable pin also wasn't being picked up by `MicroNMEALocationProvider`
because of a mismatch in constant naming conventions. I did a general
cleanup of the GPS and ThinkNode M3 bring-up code so that constant names
line up and "*_ACTIVE" constants are used consistently vs hardcoding
`HIGH`/`LOW`. After making these changes, serial data immediately starts
streaming in from the NMEA on boot and GPS detection just works.
LED handling was also not quite right for the ThinkNode M3. The LoRa TX
LED was being driven high to turn it on when it should actually be
driven low. I changed the code to use the `LED_STATE_ON` constant and
also added a little code to the shutdown path to properly make sure that
all LEDs are turned off.
Tested and confirmed working on real hardware.
Resolves both #1864 and #2879.
hasSeen() was simultaneously a predicate and a mutator — it inserted the
packet hash on every miss, making five call sites that only wanted to mark
a packet as sent call it with the return value discarded.
Split into:
- wasSeen() — pure predicate, no side effects
- markSeen() — explicit insert
All query sites now call markSeen() immediately after wasSeen() returns
false, preserving identical runtime behaviour. The five mark-only send
sites (sendFlood, sendDirect, sendZeroHop x2) now call markSeen directly.
Also fixes three bridge sites (BridgeBase, ESPNowBridge, RS232Bridge)
that had the same query+implicit-insert pattern.
Tests: add test/test_mesh_tables/ covering wasSeen purity, markSeen,
dup stats, and clear. Update SHA256 mock to produce deterministic output
(previously finalize() was a no-op). Add Packet.cpp to native build filter.
- Added build flag "SX126X_USE_REGULATOR_LDO" (set to 1 to enable) to use LDO for the SX1262 radio instead of DC-DC when the DCDC pin isn't wired up (e.g. t-echo lite)
- Added additional debug mode diagnostic messages during SX1262 init to better highlight faults