- AES-128-CCM for frame encryption + integrity (single primitive).
- HKDF-SHA256 (ESP) or CMAC-KDF (AVR) for key derivation.
- Ed25519 verify (ESP only) for signed firmware + admin commands; AVR uses
HMAC-SHA256 with
AdminKeyinstead. - CSPRNG: SX127x RSSI noise +
micros()jitter mixed via SHA1/AES-CTR DRBG.
NetworkKey NK -- realm-wide, pre-shared
NodeIdentityKey IK_n -- per node, provisioned
SessionKey SK_{a,b} -- per peer pair, rotated
GroupKey GK_g -- per group channel
AdminKey AK -- pubkey (Ed25519) or shared HMAC key
- Admin runs
tools/provisioner/provision.py. - Tool generates
node_id,IK_n, setsNK,admin_pubkey. - Writes to EEPROM (AVR) / LittleFS NVS partition (ESP).
- Sealed: blob is HMACed with a board-unique fuse-derived key when available.
- Nonce (13 B):
SRC(4) || SEQ(4) || dir(1) || epoch_min(4). - AAD: 18 B header (MV..NF).
- Tag: 4 B for control, 8 B for data/admin.
- Plaintext payload max = 200 − 18 (hdr) − 8 (tag) = 174 B.
- 64-bit sliding bitmap per
(peer, dir). - Reject if
seq ≤ hi - 64or bit set. - Persist
seq_hievery 256 increments to EEPROM (rollback resistance).
Format: ADMIN_CMD = { cmd_id, args, ts, sig } where sig is
Ed25519(AdminKey_priv, hash(everything-before)) on ESP, or HMAC on AVR.
Permitted commands: set_role, add_blacklist, remove_blacklist, rekey,
reboot, ota_begin (ESP only), set_tx_power, dump_stats.
Per-neighbor sliding-window counters (1-min, 10-min):
rx_rate,mic_fail,crc_err,dup_rate,rreq_rate.
Trust score T ∈ [0,100], default 70.
| Event | ΔT |
|---|---|
| MIC fail | −20 |
| CRC > 30% | −5 |
| RREQ storm | −15 + blacklist 10 min |
| Successful ACK | +1 (cap 100) |
| Stale > 1 h | decay −1 |
Actions:
T < 30: drop all frames from peer.30 ≤ T < 60: relay only, do not deliver to app.T ≥ 60: normal.
Reports flagged events via IDS_REPORT to nearest admin.
- Signed image:
image || Ed25519(sig). - Bootloader (rBoot fork) verifies signature against burned admin pubkey before swapping slot.
- AVR: best-effort CRC; signed OTA out of scope for AVR.